17db96d56Sopenharmony_ci/* Dictionary object implementation using a hash table */
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ci/* The distribution includes a separate file, Objects/dictnotes.txt,
47db96d56Sopenharmony_ci   describing explorations into dictionary design and optimization.
57db96d56Sopenharmony_ci   It covers typical dictionary use patterns, the parameters for
67db96d56Sopenharmony_ci   tuning dictionaries, and several ideas for possible optimizations.
77db96d56Sopenharmony_ci*/
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_ci/* PyDictKeysObject
107db96d56Sopenharmony_ci
117db96d56Sopenharmony_ciThis implements the dictionary's hashtable.
127db96d56Sopenharmony_ci
137db96d56Sopenharmony_ciAs of Python 3.6, this is compact and ordered. Basic idea is described here:
147db96d56Sopenharmony_ci* https://mail.python.org/pipermail/python-dev/2012-December/123028.html
157db96d56Sopenharmony_ci* https://morepypy.blogspot.com/2015/01/faster-more-memory-efficient-and-more.html
167db96d56Sopenharmony_ci
177db96d56Sopenharmony_cilayout:
187db96d56Sopenharmony_ci
197db96d56Sopenharmony_ci+---------------------+
207db96d56Sopenharmony_ci| dk_refcnt           |
217db96d56Sopenharmony_ci| dk_log2_size        |
227db96d56Sopenharmony_ci| dk_log2_index_bytes |
237db96d56Sopenharmony_ci| dk_kind             |
247db96d56Sopenharmony_ci| dk_usable           |
257db96d56Sopenharmony_ci| dk_nentries         |
267db96d56Sopenharmony_ci+---------------------+
277db96d56Sopenharmony_ci| dk_indices[]        |
287db96d56Sopenharmony_ci|                     |
297db96d56Sopenharmony_ci+---------------------+
307db96d56Sopenharmony_ci| dk_entries[]        |
317db96d56Sopenharmony_ci|                     |
327db96d56Sopenharmony_ci+---------------------+
337db96d56Sopenharmony_ci
347db96d56Sopenharmony_cidk_indices is actual hashtable.  It holds index in entries, or DKIX_EMPTY(-1)
357db96d56Sopenharmony_cior DKIX_DUMMY(-2).
367db96d56Sopenharmony_ciSize of indices is dk_size.  Type of each index in indices is vary on dk_size:
377db96d56Sopenharmony_ci
387db96d56Sopenharmony_ci* int8  for          dk_size <= 128
397db96d56Sopenharmony_ci* int16 for 256   <= dk_size <= 2**15
407db96d56Sopenharmony_ci* int32 for 2**16 <= dk_size <= 2**31
417db96d56Sopenharmony_ci* int64 for 2**32 <= dk_size
427db96d56Sopenharmony_ci
437db96d56Sopenharmony_cidk_entries is array of PyDictKeyEntry when dk_kind == DICT_KEYS_GENERAL or
447db96d56Sopenharmony_ciPyDictUnicodeEntry otherwise. Its length is USABLE_FRACTION(dk_size).
457db96d56Sopenharmony_ci
467db96d56Sopenharmony_ciNOTE: Since negative value is used for DKIX_EMPTY and DKIX_DUMMY, type of
477db96d56Sopenharmony_cidk_indices entry is signed integer and int16 is used for table which
487db96d56Sopenharmony_cidk_size == 256.
497db96d56Sopenharmony_ci*/
507db96d56Sopenharmony_ci
517db96d56Sopenharmony_ci
527db96d56Sopenharmony_ci/*
537db96d56Sopenharmony_ciThe DictObject can be in one of two forms.
547db96d56Sopenharmony_ci
557db96d56Sopenharmony_ciEither:
567db96d56Sopenharmony_ci  A combined table:
577db96d56Sopenharmony_ci    ma_values == NULL, dk_refcnt == 1.
587db96d56Sopenharmony_ci    Values are stored in the me_value field of the PyDictKeysObject.
597db96d56Sopenharmony_ciOr:
607db96d56Sopenharmony_ci  A split table:
617db96d56Sopenharmony_ci    ma_values != NULL, dk_refcnt >= 1
627db96d56Sopenharmony_ci    Values are stored in the ma_values array.
637db96d56Sopenharmony_ci    Only string (unicode) keys are allowed.
647db96d56Sopenharmony_ci
657db96d56Sopenharmony_ciThere are four kinds of slots in the table (slot is index, and
667db96d56Sopenharmony_ciDK_ENTRIES(keys)[index] if index >= 0):
677db96d56Sopenharmony_ci
687db96d56Sopenharmony_ci1. Unused.  index == DKIX_EMPTY
697db96d56Sopenharmony_ci   Does not hold an active (key, value) pair now and never did.  Unused can
707db96d56Sopenharmony_ci   transition to Active upon key insertion.  This is each slot's initial state.
717db96d56Sopenharmony_ci
727db96d56Sopenharmony_ci2. Active.  index >= 0, me_key != NULL and me_value != NULL
737db96d56Sopenharmony_ci   Holds an active (key, value) pair.  Active can transition to Dummy or
747db96d56Sopenharmony_ci   Pending upon key deletion (for combined and split tables respectively).
757db96d56Sopenharmony_ci   This is the only case in which me_value != NULL.
767db96d56Sopenharmony_ci
777db96d56Sopenharmony_ci3. Dummy.  index == DKIX_DUMMY  (combined only)
787db96d56Sopenharmony_ci   Previously held an active (key, value) pair, but that was deleted and an
797db96d56Sopenharmony_ci   active pair has not yet overwritten the slot.  Dummy can transition to
807db96d56Sopenharmony_ci   Active upon key insertion.  Dummy slots cannot be made Unused again
817db96d56Sopenharmony_ci   else the probe sequence in case of collision would have no way to know
827db96d56Sopenharmony_ci   they were once active.
837db96d56Sopenharmony_ci
847db96d56Sopenharmony_ci4. Pending. index >= 0, key != NULL, and value == NULL  (split only)
857db96d56Sopenharmony_ci   Not yet inserted in split-table.
867db96d56Sopenharmony_ci*/
877db96d56Sopenharmony_ci
887db96d56Sopenharmony_ci/*
897db96d56Sopenharmony_ciPreserving insertion order
907db96d56Sopenharmony_ci
917db96d56Sopenharmony_ciIt's simple for combined table.  Since dk_entries is mostly append only, we can
927db96d56Sopenharmony_ciget insertion order by just iterating dk_entries.
937db96d56Sopenharmony_ci
947db96d56Sopenharmony_ciOne exception is .popitem().  It removes last item in dk_entries and decrement
957db96d56Sopenharmony_cidk_nentries to achieve amortized O(1).  Since there are DKIX_DUMMY remains in
967db96d56Sopenharmony_cidk_indices, we can't increment dk_usable even though dk_nentries is
977db96d56Sopenharmony_cidecremented.
987db96d56Sopenharmony_ci
997db96d56Sopenharmony_ciTo preserve the order in a split table, a bit vector is used  to record the
1007db96d56Sopenharmony_ciinsertion order. When a key is inserted the bit vector is shifted up by 4 bits
1017db96d56Sopenharmony_ciand the index of the key is stored in the low 4 bits.
1027db96d56Sopenharmony_ciAs a consequence of this, split keys have a maximum size of 16.
1037db96d56Sopenharmony_ci*/
1047db96d56Sopenharmony_ci
1057db96d56Sopenharmony_ci/* PyDict_MINSIZE is the starting size for any new dict.
1067db96d56Sopenharmony_ci * 8 allows dicts with no more than 5 active entries; experiments suggested
1077db96d56Sopenharmony_ci * this suffices for the majority of dicts (consisting mostly of usually-small
1087db96d56Sopenharmony_ci * dicts created to pass keyword arguments).
1097db96d56Sopenharmony_ci * Making this 8, rather than 4 reduces the number of resizes for most
1107db96d56Sopenharmony_ci * dictionaries, without any significant extra memory use.
1117db96d56Sopenharmony_ci */
1127db96d56Sopenharmony_ci#define PyDict_LOG_MINSIZE 3
1137db96d56Sopenharmony_ci#define PyDict_MINSIZE 8
1147db96d56Sopenharmony_ci
1157db96d56Sopenharmony_ci#include "Python.h"
1167db96d56Sopenharmony_ci#include "pycore_bitutils.h"      // _Py_bit_length
1177db96d56Sopenharmony_ci#include "pycore_call.h"          // _PyObject_CallNoArgs()
1187db96d56Sopenharmony_ci#include "pycore_code.h"          // stats
1197db96d56Sopenharmony_ci#include "pycore_dict.h"          // PyDictKeysObject
1207db96d56Sopenharmony_ci#include "pycore_gc.h"            // _PyObject_GC_IS_TRACKED()
1217db96d56Sopenharmony_ci#include "pycore_object.h"        // _PyObject_GC_TRACK()
1227db96d56Sopenharmony_ci#include "pycore_pyerrors.h"      // _PyErr_Fetch()
1237db96d56Sopenharmony_ci#include "pycore_pystate.h"       // _PyThreadState_GET()
1247db96d56Sopenharmony_ci#include "stringlib/eq.h"         // unicode_eq()
1257db96d56Sopenharmony_ci
1267db96d56Sopenharmony_ci#include <stdbool.h>
1277db96d56Sopenharmony_ci
1287db96d56Sopenharmony_ci/*[clinic input]
1297db96d56Sopenharmony_ciclass dict "PyDictObject *" "&PyDict_Type"
1307db96d56Sopenharmony_ci[clinic start generated code]*/
1317db96d56Sopenharmony_ci/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f157a5a0ce9589d6]*/
1327db96d56Sopenharmony_ci
1337db96d56Sopenharmony_ci
1347db96d56Sopenharmony_ci/*
1357db96d56Sopenharmony_ciTo ensure the lookup algorithm terminates, there must be at least one Unused
1367db96d56Sopenharmony_cislot (NULL key) in the table.
1377db96d56Sopenharmony_ciTo avoid slowing down lookups on a near-full table, we resize the table when
1387db96d56Sopenharmony_ciit's USABLE_FRACTION (currently two-thirds) full.
1397db96d56Sopenharmony_ci*/
1407db96d56Sopenharmony_ci
1417db96d56Sopenharmony_ci#define PERTURB_SHIFT 5
1427db96d56Sopenharmony_ci
1437db96d56Sopenharmony_ci/*
1447db96d56Sopenharmony_ciMajor subtleties ahead:  Most hash schemes depend on having a "good" hash
1457db96d56Sopenharmony_cifunction, in the sense of simulating randomness.  Python doesn't:  its most
1467db96d56Sopenharmony_ciimportant hash functions (for ints) are very regular in common
1477db96d56Sopenharmony_cicases:
1487db96d56Sopenharmony_ci
1497db96d56Sopenharmony_ci  >>>[hash(i) for i in range(4)]
1507db96d56Sopenharmony_ci  [0, 1, 2, 3]
1517db96d56Sopenharmony_ci
1527db96d56Sopenharmony_ciThis isn't necessarily bad!  To the contrary, in a table of size 2**i, taking
1537db96d56Sopenharmony_cithe low-order i bits as the initial table index is extremely fast, and there
1547db96d56Sopenharmony_ciare no collisions at all for dicts indexed by a contiguous range of ints. So
1557db96d56Sopenharmony_cithis gives better-than-random behavior in common cases, and that's very
1567db96d56Sopenharmony_cidesirable.
1577db96d56Sopenharmony_ci
1587db96d56Sopenharmony_ciOTOH, when collisions occur, the tendency to fill contiguous slices of the
1597db96d56Sopenharmony_cihash table makes a good collision resolution strategy crucial.  Taking only
1607db96d56Sopenharmony_cithe last i bits of the hash code is also vulnerable:  for example, consider
1617db96d56Sopenharmony_cithe list [i << 16 for i in range(20000)] as a set of keys.  Since ints are
1627db96d56Sopenharmony_citheir own hash codes, and this fits in a dict of size 2**15, the last 15 bits
1637db96d56Sopenharmony_ci of every hash code are all 0:  they *all* map to the same table index.
1647db96d56Sopenharmony_ci
1657db96d56Sopenharmony_ciBut catering to unusual cases should not slow the usual ones, so we just take
1667db96d56Sopenharmony_cithe last i bits anyway.  It's up to collision resolution to do the rest.  If
1677db96d56Sopenharmony_ciwe *usually* find the key we're looking for on the first try (and, it turns
1687db96d56Sopenharmony_ciout, we usually do -- the table load factor is kept under 2/3, so the odds
1697db96d56Sopenharmony_ciare solidly in our favor), then it makes best sense to keep the initial index
1707db96d56Sopenharmony_cicomputation dirt cheap.
1717db96d56Sopenharmony_ci
1727db96d56Sopenharmony_ciThe first half of collision resolution is to visit table indices via this
1737db96d56Sopenharmony_cirecurrence:
1747db96d56Sopenharmony_ci
1757db96d56Sopenharmony_ci    j = ((5*j) + 1) mod 2**i
1767db96d56Sopenharmony_ci
1777db96d56Sopenharmony_ciFor any initial j in range(2**i), repeating that 2**i times generates each
1787db96d56Sopenharmony_ciint in range(2**i) exactly once (see any text on random-number generation for
1797db96d56Sopenharmony_ciproof).  By itself, this doesn't help much:  like linear probing (setting
1807db96d56Sopenharmony_cij += 1, or j -= 1, on each loop trip), it scans the table entries in a fixed
1817db96d56Sopenharmony_ciorder.  This would be bad, except that's not the only thing we do, and it's
1827db96d56Sopenharmony_ciactually *good* in the common cases where hash keys are consecutive.  In an
1837db96d56Sopenharmony_ciexample that's really too small to make this entirely clear, for a table of
1847db96d56Sopenharmony_cisize 2**3 the order of indices is:
1857db96d56Sopenharmony_ci
1867db96d56Sopenharmony_ci    0 -> 1 -> 6 -> 7 -> 4 -> 5 -> 2 -> 3 -> 0 [and here it's repeating]
1877db96d56Sopenharmony_ci
1887db96d56Sopenharmony_ciIf two things come in at index 5, the first place we look after is index 2,
1897db96d56Sopenharmony_cinot 6, so if another comes in at index 6 the collision at 5 didn't hurt it.
1907db96d56Sopenharmony_ciLinear probing is deadly in this case because there the fixed probe order
1917db96d56Sopenharmony_ciis the *same* as the order consecutive keys are likely to arrive.  But it's
1927db96d56Sopenharmony_ciextremely unlikely hash codes will follow a 5*j+1 recurrence by accident,
1937db96d56Sopenharmony_ciand certain that consecutive hash codes do not.
1947db96d56Sopenharmony_ci
1957db96d56Sopenharmony_ciThe other half of the strategy is to get the other bits of the hash code
1967db96d56Sopenharmony_ciinto play.  This is done by initializing a (unsigned) vrbl "perturb" to the
1977db96d56Sopenharmony_cifull hash code, and changing the recurrence to:
1987db96d56Sopenharmony_ci
1997db96d56Sopenharmony_ci    perturb >>= PERTURB_SHIFT;
2007db96d56Sopenharmony_ci    j = (5*j) + 1 + perturb;
2017db96d56Sopenharmony_ci    use j % 2**i as the next table index;
2027db96d56Sopenharmony_ci
2037db96d56Sopenharmony_ciNow the probe sequence depends (eventually) on every bit in the hash code,
2047db96d56Sopenharmony_ciand the pseudo-scrambling property of recurring on 5*j+1 is more valuable,
2057db96d56Sopenharmony_cibecause it quickly magnifies small differences in the bits that didn't affect
2067db96d56Sopenharmony_cithe initial index.  Note that because perturb is unsigned, if the recurrence
2077db96d56Sopenharmony_ciis executed often enough perturb eventually becomes and remains 0.  At that
2087db96d56Sopenharmony_cipoint (very rarely reached) the recurrence is on (just) 5*j+1 again, and
2097db96d56Sopenharmony_cithat's certain to find an empty slot eventually (since it generates every int
2107db96d56Sopenharmony_ciin range(2**i), and we make sure there's always at least one empty slot).
2117db96d56Sopenharmony_ci
2127db96d56Sopenharmony_ciSelecting a good value for PERTURB_SHIFT is a balancing act.  You want it
2137db96d56Sopenharmony_cismall so that the high bits of the hash code continue to affect the probe
2147db96d56Sopenharmony_cisequence across iterations; but you want it large so that in really bad cases
2157db96d56Sopenharmony_cithe high-order hash bits have an effect on early iterations.  5 was "the
2167db96d56Sopenharmony_cibest" in minimizing total collisions across experiments Tim Peters ran (on
2177db96d56Sopenharmony_ciboth normal and pathological cases), but 4 and 6 weren't significantly worse.
2187db96d56Sopenharmony_ci
2197db96d56Sopenharmony_ciHistorical: Reimer Behrends contributed the idea of using a polynomial-based
2207db96d56Sopenharmony_ciapproach, using repeated multiplication by x in GF(2**n) where an irreducible
2217db96d56Sopenharmony_cipolynomial for each table size was chosen such that x was a primitive root.
2227db96d56Sopenharmony_ciChristian Tismer later extended that to use division by x instead, as an
2237db96d56Sopenharmony_ciefficient way to get the high bits of the hash code into play.  This scheme
2247db96d56Sopenharmony_cialso gave excellent collision statistics, but was more expensive:  two
2257db96d56Sopenharmony_ciif-tests were required inside the loop; computing "the next" index took about
2267db96d56Sopenharmony_cithe same number of operations but without as much potential parallelism
2277db96d56Sopenharmony_ci(e.g., computing 5*j can go on at the same time as computing 1+perturb in the
2287db96d56Sopenharmony_ciabove, and then shifting perturb can be done while the table index is being
2297db96d56Sopenharmony_cimasked); and the PyDictObject struct required a member to hold the table's
2307db96d56Sopenharmony_cipolynomial.  In Tim's experiments the current scheme ran faster, produced
2317db96d56Sopenharmony_ciequally good collision statistics, needed less code & used less memory.
2327db96d56Sopenharmony_ci
2337db96d56Sopenharmony_ci*/
2347db96d56Sopenharmony_ci
2357db96d56Sopenharmony_cistatic int dictresize(PyDictObject *mp, uint8_t log_newsize, int unicode);
2367db96d56Sopenharmony_ci
2377db96d56Sopenharmony_cistatic PyObject* dict_iter(PyDictObject *dict);
2387db96d56Sopenharmony_ci
2397db96d56Sopenharmony_ci/*Global counter used to set ma_version_tag field of dictionary.
2407db96d56Sopenharmony_ci * It is incremented each time that a dictionary is created and each
2417db96d56Sopenharmony_ci * time that a dictionary is modified. */
2427db96d56Sopenharmony_ciuint64_t _pydict_global_version = 0;
2437db96d56Sopenharmony_ci
2447db96d56Sopenharmony_ci#include "clinic/dictobject.c.h"
2457db96d56Sopenharmony_ci
2467db96d56Sopenharmony_ci
2477db96d56Sopenharmony_ci#if PyDict_MAXFREELIST > 0
2487db96d56Sopenharmony_cistatic struct _Py_dict_state *
2497db96d56Sopenharmony_ciget_dict_state(void)
2507db96d56Sopenharmony_ci{
2517db96d56Sopenharmony_ci    PyInterpreterState *interp = _PyInterpreterState_GET();
2527db96d56Sopenharmony_ci    return &interp->dict_state;
2537db96d56Sopenharmony_ci}
2547db96d56Sopenharmony_ci#endif
2557db96d56Sopenharmony_ci
2567db96d56Sopenharmony_ci
2577db96d56Sopenharmony_civoid
2587db96d56Sopenharmony_ci_PyDict_ClearFreeList(PyInterpreterState *interp)
2597db96d56Sopenharmony_ci{
2607db96d56Sopenharmony_ci#if PyDict_MAXFREELIST > 0
2617db96d56Sopenharmony_ci    struct _Py_dict_state *state = &interp->dict_state;
2627db96d56Sopenharmony_ci    while (state->numfree) {
2637db96d56Sopenharmony_ci        PyDictObject *op = state->free_list[--state->numfree];
2647db96d56Sopenharmony_ci        assert(PyDict_CheckExact(op));
2657db96d56Sopenharmony_ci        PyObject_GC_Del(op);
2667db96d56Sopenharmony_ci    }
2677db96d56Sopenharmony_ci    while (state->keys_numfree) {
2687db96d56Sopenharmony_ci        PyObject_Free(state->keys_free_list[--state->keys_numfree]);
2697db96d56Sopenharmony_ci    }
2707db96d56Sopenharmony_ci#endif
2717db96d56Sopenharmony_ci}
2727db96d56Sopenharmony_ci
2737db96d56Sopenharmony_ci
2747db96d56Sopenharmony_civoid
2757db96d56Sopenharmony_ci_PyDict_Fini(PyInterpreterState *interp)
2767db96d56Sopenharmony_ci{
2777db96d56Sopenharmony_ci    _PyDict_ClearFreeList(interp);
2787db96d56Sopenharmony_ci#if defined(Py_DEBUG) && PyDict_MAXFREELIST > 0
2797db96d56Sopenharmony_ci    struct _Py_dict_state *state = &interp->dict_state;
2807db96d56Sopenharmony_ci    state->numfree = -1;
2817db96d56Sopenharmony_ci    state->keys_numfree = -1;
2827db96d56Sopenharmony_ci#endif
2837db96d56Sopenharmony_ci}
2847db96d56Sopenharmony_ci
2857db96d56Sopenharmony_cistatic inline Py_hash_t
2867db96d56Sopenharmony_ciunicode_get_hash(PyObject *o)
2877db96d56Sopenharmony_ci{
2887db96d56Sopenharmony_ci    assert(PyUnicode_CheckExact(o));
2897db96d56Sopenharmony_ci    return _PyASCIIObject_CAST(o)->hash;
2907db96d56Sopenharmony_ci}
2917db96d56Sopenharmony_ci
2927db96d56Sopenharmony_ci/* Print summary info about the state of the optimized allocator */
2937db96d56Sopenharmony_civoid
2947db96d56Sopenharmony_ci_PyDict_DebugMallocStats(FILE *out)
2957db96d56Sopenharmony_ci{
2967db96d56Sopenharmony_ci#if PyDict_MAXFREELIST > 0
2977db96d56Sopenharmony_ci    struct _Py_dict_state *state = get_dict_state();
2987db96d56Sopenharmony_ci    _PyDebugAllocatorStats(out, "free PyDictObject",
2997db96d56Sopenharmony_ci                           state->numfree, sizeof(PyDictObject));
3007db96d56Sopenharmony_ci#endif
3017db96d56Sopenharmony_ci}
3027db96d56Sopenharmony_ci
3037db96d56Sopenharmony_ci#define DK_MASK(dk) (DK_SIZE(dk)-1)
3047db96d56Sopenharmony_ci
3057db96d56Sopenharmony_cistatic void free_keys_object(PyDictKeysObject *keys);
3067db96d56Sopenharmony_ci
3077db96d56Sopenharmony_cistatic inline void
3087db96d56Sopenharmony_cidictkeys_incref(PyDictKeysObject *dk)
3097db96d56Sopenharmony_ci{
3107db96d56Sopenharmony_ci#ifdef Py_REF_DEBUG
3117db96d56Sopenharmony_ci    _Py_RefTotal++;
3127db96d56Sopenharmony_ci#endif
3137db96d56Sopenharmony_ci    dk->dk_refcnt++;
3147db96d56Sopenharmony_ci}
3157db96d56Sopenharmony_ci
3167db96d56Sopenharmony_cistatic inline void
3177db96d56Sopenharmony_cidictkeys_decref(PyDictKeysObject *dk)
3187db96d56Sopenharmony_ci{
3197db96d56Sopenharmony_ci    assert(dk->dk_refcnt > 0);
3207db96d56Sopenharmony_ci#ifdef Py_REF_DEBUG
3217db96d56Sopenharmony_ci    _Py_RefTotal--;
3227db96d56Sopenharmony_ci#endif
3237db96d56Sopenharmony_ci    if (--dk->dk_refcnt == 0) {
3247db96d56Sopenharmony_ci        free_keys_object(dk);
3257db96d56Sopenharmony_ci    }
3267db96d56Sopenharmony_ci}
3277db96d56Sopenharmony_ci
3287db96d56Sopenharmony_ci/* lookup indices.  returns DKIX_EMPTY, DKIX_DUMMY, or ix >=0 */
3297db96d56Sopenharmony_cistatic inline Py_ssize_t
3307db96d56Sopenharmony_cidictkeys_get_index(const PyDictKeysObject *keys, Py_ssize_t i)
3317db96d56Sopenharmony_ci{
3327db96d56Sopenharmony_ci    int log2size = DK_LOG_SIZE(keys);
3337db96d56Sopenharmony_ci    Py_ssize_t ix;
3347db96d56Sopenharmony_ci
3357db96d56Sopenharmony_ci    if (log2size < 8) {
3367db96d56Sopenharmony_ci        const int8_t *indices = (const int8_t*)(keys->dk_indices);
3377db96d56Sopenharmony_ci        ix = indices[i];
3387db96d56Sopenharmony_ci    }
3397db96d56Sopenharmony_ci    else if (log2size < 16) {
3407db96d56Sopenharmony_ci        const int16_t *indices = (const int16_t*)(keys->dk_indices);
3417db96d56Sopenharmony_ci        ix = indices[i];
3427db96d56Sopenharmony_ci    }
3437db96d56Sopenharmony_ci#if SIZEOF_VOID_P > 4
3447db96d56Sopenharmony_ci    else if (log2size >= 32) {
3457db96d56Sopenharmony_ci        const int64_t *indices = (const int64_t*)(keys->dk_indices);
3467db96d56Sopenharmony_ci        ix = indices[i];
3477db96d56Sopenharmony_ci    }
3487db96d56Sopenharmony_ci#endif
3497db96d56Sopenharmony_ci    else {
3507db96d56Sopenharmony_ci        const int32_t *indices = (const int32_t*)(keys->dk_indices);
3517db96d56Sopenharmony_ci        ix = indices[i];
3527db96d56Sopenharmony_ci    }
3537db96d56Sopenharmony_ci    assert(ix >= DKIX_DUMMY);
3547db96d56Sopenharmony_ci    return ix;
3557db96d56Sopenharmony_ci}
3567db96d56Sopenharmony_ci
3577db96d56Sopenharmony_ci/* write to indices. */
3587db96d56Sopenharmony_cistatic inline void
3597db96d56Sopenharmony_cidictkeys_set_index(PyDictKeysObject *keys, Py_ssize_t i, Py_ssize_t ix)
3607db96d56Sopenharmony_ci{
3617db96d56Sopenharmony_ci    int log2size = DK_LOG_SIZE(keys);
3627db96d56Sopenharmony_ci
3637db96d56Sopenharmony_ci    assert(ix >= DKIX_DUMMY);
3647db96d56Sopenharmony_ci    assert(keys->dk_version == 0);
3657db96d56Sopenharmony_ci
3667db96d56Sopenharmony_ci    if (log2size < 8) {
3677db96d56Sopenharmony_ci        int8_t *indices = (int8_t*)(keys->dk_indices);
3687db96d56Sopenharmony_ci        assert(ix <= 0x7f);
3697db96d56Sopenharmony_ci        indices[i] = (char)ix;
3707db96d56Sopenharmony_ci    }
3717db96d56Sopenharmony_ci    else if (log2size < 16) {
3727db96d56Sopenharmony_ci        int16_t *indices = (int16_t*)(keys->dk_indices);
3737db96d56Sopenharmony_ci        assert(ix <= 0x7fff);
3747db96d56Sopenharmony_ci        indices[i] = (int16_t)ix;
3757db96d56Sopenharmony_ci    }
3767db96d56Sopenharmony_ci#if SIZEOF_VOID_P > 4
3777db96d56Sopenharmony_ci    else if (log2size >= 32) {
3787db96d56Sopenharmony_ci        int64_t *indices = (int64_t*)(keys->dk_indices);
3797db96d56Sopenharmony_ci        indices[i] = ix;
3807db96d56Sopenharmony_ci    }
3817db96d56Sopenharmony_ci#endif
3827db96d56Sopenharmony_ci    else {
3837db96d56Sopenharmony_ci        int32_t *indices = (int32_t*)(keys->dk_indices);
3847db96d56Sopenharmony_ci        assert(ix <= 0x7fffffff);
3857db96d56Sopenharmony_ci        indices[i] = (int32_t)ix;
3867db96d56Sopenharmony_ci    }
3877db96d56Sopenharmony_ci}
3887db96d56Sopenharmony_ci
3897db96d56Sopenharmony_ci
3907db96d56Sopenharmony_ci/* USABLE_FRACTION is the maximum dictionary load.
3917db96d56Sopenharmony_ci * Increasing this ratio makes dictionaries more dense resulting in more
3927db96d56Sopenharmony_ci * collisions.  Decreasing it improves sparseness at the expense of spreading
3937db96d56Sopenharmony_ci * indices over more cache lines and at the cost of total memory consumed.
3947db96d56Sopenharmony_ci *
3957db96d56Sopenharmony_ci * USABLE_FRACTION must obey the following:
3967db96d56Sopenharmony_ci *     (0 < USABLE_FRACTION(n) < n) for all n >= 2
3977db96d56Sopenharmony_ci *
3987db96d56Sopenharmony_ci * USABLE_FRACTION should be quick to calculate.
3997db96d56Sopenharmony_ci * Fractions around 1/2 to 2/3 seem to work well in practice.
4007db96d56Sopenharmony_ci */
4017db96d56Sopenharmony_ci#define USABLE_FRACTION(n) (((n) << 1)/3)
4027db96d56Sopenharmony_ci
4037db96d56Sopenharmony_ci/* Find the smallest dk_size >= minsize. */
4047db96d56Sopenharmony_cistatic inline uint8_t
4057db96d56Sopenharmony_cicalculate_log2_keysize(Py_ssize_t minsize)
4067db96d56Sopenharmony_ci{
4077db96d56Sopenharmony_ci#if SIZEOF_LONG == SIZEOF_SIZE_T
4087db96d56Sopenharmony_ci    minsize = (minsize | PyDict_MINSIZE) - 1;
4097db96d56Sopenharmony_ci    return _Py_bit_length(minsize | (PyDict_MINSIZE-1));
4107db96d56Sopenharmony_ci#elif defined(_MSC_VER)
4117db96d56Sopenharmony_ci    // On 64bit Windows, sizeof(long) == 4.
4127db96d56Sopenharmony_ci    minsize = (minsize | PyDict_MINSIZE) - 1;
4137db96d56Sopenharmony_ci    unsigned long msb;
4147db96d56Sopenharmony_ci    _BitScanReverse64(&msb, (uint64_t)minsize);
4157db96d56Sopenharmony_ci    return (uint8_t)(msb + 1);
4167db96d56Sopenharmony_ci#else
4177db96d56Sopenharmony_ci    uint8_t log2_size;
4187db96d56Sopenharmony_ci    for (log2_size = PyDict_LOG_MINSIZE;
4197db96d56Sopenharmony_ci            (((Py_ssize_t)1) << log2_size) < minsize;
4207db96d56Sopenharmony_ci            log2_size++)
4217db96d56Sopenharmony_ci        ;
4227db96d56Sopenharmony_ci    return log2_size;
4237db96d56Sopenharmony_ci#endif
4247db96d56Sopenharmony_ci}
4257db96d56Sopenharmony_ci
4267db96d56Sopenharmony_ci/* estimate_keysize is reverse function of USABLE_FRACTION.
4277db96d56Sopenharmony_ci *
4287db96d56Sopenharmony_ci * This can be used to reserve enough size to insert n entries without
4297db96d56Sopenharmony_ci * resizing.
4307db96d56Sopenharmony_ci */
4317db96d56Sopenharmony_cistatic inline uint8_t
4327db96d56Sopenharmony_ciestimate_log2_keysize(Py_ssize_t n)
4337db96d56Sopenharmony_ci{
4347db96d56Sopenharmony_ci    return calculate_log2_keysize((n*3 + 1) / 2);
4357db96d56Sopenharmony_ci}
4367db96d56Sopenharmony_ci
4377db96d56Sopenharmony_ci
4387db96d56Sopenharmony_ci/* GROWTH_RATE. Growth rate upon hitting maximum load.
4397db96d56Sopenharmony_ci * Currently set to used*3.
4407db96d56Sopenharmony_ci * This means that dicts double in size when growing without deletions,
4417db96d56Sopenharmony_ci * but have more head room when the number of deletions is on a par with the
4427db96d56Sopenharmony_ci * number of insertions.  See also bpo-17563 and bpo-33205.
4437db96d56Sopenharmony_ci *
4447db96d56Sopenharmony_ci * GROWTH_RATE was set to used*4 up to version 3.2.
4457db96d56Sopenharmony_ci * GROWTH_RATE was set to used*2 in version 3.3.0
4467db96d56Sopenharmony_ci * GROWTH_RATE was set to used*2 + capacity/2 in 3.4.0-3.6.0.
4477db96d56Sopenharmony_ci */
4487db96d56Sopenharmony_ci#define GROWTH_RATE(d) ((d)->ma_used*3)
4497db96d56Sopenharmony_ci
4507db96d56Sopenharmony_ci/* This immutable, empty PyDictKeysObject is used for PyDict_Clear()
4517db96d56Sopenharmony_ci * (which cannot fail and thus can do no allocation).
4527db96d56Sopenharmony_ci */
4537db96d56Sopenharmony_cistatic PyDictKeysObject empty_keys_struct = {
4547db96d56Sopenharmony_ci        1, /* dk_refcnt */
4557db96d56Sopenharmony_ci        0, /* dk_log2_size */
4567db96d56Sopenharmony_ci        0, /* dk_log2_index_bytes */
4577db96d56Sopenharmony_ci        DICT_KEYS_UNICODE, /* dk_kind */
4587db96d56Sopenharmony_ci        1, /* dk_version */
4597db96d56Sopenharmony_ci        0, /* dk_usable (immutable) */
4607db96d56Sopenharmony_ci        0, /* dk_nentries */
4617db96d56Sopenharmony_ci        {DKIX_EMPTY, DKIX_EMPTY, DKIX_EMPTY, DKIX_EMPTY,
4627db96d56Sopenharmony_ci         DKIX_EMPTY, DKIX_EMPTY, DKIX_EMPTY, DKIX_EMPTY}, /* dk_indices */
4637db96d56Sopenharmony_ci};
4647db96d56Sopenharmony_ci
4657db96d56Sopenharmony_ci#define Py_EMPTY_KEYS &empty_keys_struct
4667db96d56Sopenharmony_ci
4677db96d56Sopenharmony_ci/* Uncomment to check the dict content in _PyDict_CheckConsistency() */
4687db96d56Sopenharmony_ci// #define DEBUG_PYDICT
4697db96d56Sopenharmony_ci
4707db96d56Sopenharmony_ci#ifdef DEBUG_PYDICT
4717db96d56Sopenharmony_ci#  define ASSERT_CONSISTENT(op) assert(_PyDict_CheckConsistency((PyObject *)(op), 1))
4727db96d56Sopenharmony_ci#else
4737db96d56Sopenharmony_ci#  define ASSERT_CONSISTENT(op) assert(_PyDict_CheckConsistency((PyObject *)(op), 0))
4747db96d56Sopenharmony_ci#endif
4757db96d56Sopenharmony_ci
4767db96d56Sopenharmony_cistatic inline int
4777db96d56Sopenharmony_ciget_index_from_order(PyDictObject *mp, Py_ssize_t i)
4787db96d56Sopenharmony_ci{
4797db96d56Sopenharmony_ci    assert(mp->ma_used <= SHARED_KEYS_MAX_SIZE);
4807db96d56Sopenharmony_ci    assert(i < (((char *)mp->ma_values)[-2]));
4817db96d56Sopenharmony_ci    return ((char *)mp->ma_values)[-3-i];
4827db96d56Sopenharmony_ci}
4837db96d56Sopenharmony_ci
4847db96d56Sopenharmony_ci#ifdef DEBUG_PYDICT
4857db96d56Sopenharmony_cistatic void
4867db96d56Sopenharmony_cidump_entries(PyDictKeysObject *dk)
4877db96d56Sopenharmony_ci{
4887db96d56Sopenharmony_ci    for (Py_ssize_t i = 0; i < dk->dk_nentries; i++) {
4897db96d56Sopenharmony_ci        if (DK_IS_UNICODE(dk)) {
4907db96d56Sopenharmony_ci            PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(dk)[i];
4917db96d56Sopenharmony_ci            printf("key=%p value=%p\n", ep->me_key, ep->me_value);
4927db96d56Sopenharmony_ci        }
4937db96d56Sopenharmony_ci        else {
4947db96d56Sopenharmony_ci            PyDictKeyEntry *ep = &DK_ENTRIES(dk)[i];
4957db96d56Sopenharmony_ci            printf("key=%p hash=%lx value=%p\n", ep->me_key, ep->me_hash, ep->me_value);
4967db96d56Sopenharmony_ci        }
4977db96d56Sopenharmony_ci    }
4987db96d56Sopenharmony_ci}
4997db96d56Sopenharmony_ci#endif
5007db96d56Sopenharmony_ci
5017db96d56Sopenharmony_ciint
5027db96d56Sopenharmony_ci_PyDict_CheckConsistency(PyObject *op, int check_content)
5037db96d56Sopenharmony_ci{
5047db96d56Sopenharmony_ci#define CHECK(expr) \
5057db96d56Sopenharmony_ci    do { if (!(expr)) { _PyObject_ASSERT_FAILED_MSG(op, Py_STRINGIFY(expr)); } } while (0)
5067db96d56Sopenharmony_ci
5077db96d56Sopenharmony_ci    assert(op != NULL);
5087db96d56Sopenharmony_ci    CHECK(PyDict_Check(op));
5097db96d56Sopenharmony_ci    PyDictObject *mp = (PyDictObject *)op;
5107db96d56Sopenharmony_ci
5117db96d56Sopenharmony_ci    PyDictKeysObject *keys = mp->ma_keys;
5127db96d56Sopenharmony_ci    int splitted = _PyDict_HasSplitTable(mp);
5137db96d56Sopenharmony_ci    Py_ssize_t usable = USABLE_FRACTION(DK_SIZE(keys));
5147db96d56Sopenharmony_ci
5157db96d56Sopenharmony_ci    CHECK(0 <= mp->ma_used && mp->ma_used <= usable);
5167db96d56Sopenharmony_ci    CHECK(0 <= keys->dk_usable && keys->dk_usable <= usable);
5177db96d56Sopenharmony_ci    CHECK(0 <= keys->dk_nentries && keys->dk_nentries <= usable);
5187db96d56Sopenharmony_ci    CHECK(keys->dk_usable + keys->dk_nentries <= usable);
5197db96d56Sopenharmony_ci
5207db96d56Sopenharmony_ci    if (!splitted) {
5217db96d56Sopenharmony_ci        /* combined table */
5227db96d56Sopenharmony_ci        CHECK(keys->dk_kind != DICT_KEYS_SPLIT);
5237db96d56Sopenharmony_ci        CHECK(keys->dk_refcnt == 1 || keys == Py_EMPTY_KEYS);
5247db96d56Sopenharmony_ci    }
5257db96d56Sopenharmony_ci    else {
5267db96d56Sopenharmony_ci        CHECK(keys->dk_kind == DICT_KEYS_SPLIT);
5277db96d56Sopenharmony_ci        CHECK(mp->ma_used <= SHARED_KEYS_MAX_SIZE);
5287db96d56Sopenharmony_ci    }
5297db96d56Sopenharmony_ci
5307db96d56Sopenharmony_ci    if (check_content) {
5317db96d56Sopenharmony_ci        for (Py_ssize_t i=0; i < DK_SIZE(keys); i++) {
5327db96d56Sopenharmony_ci            Py_ssize_t ix = dictkeys_get_index(keys, i);
5337db96d56Sopenharmony_ci            CHECK(DKIX_DUMMY <= ix && ix <= usable);
5347db96d56Sopenharmony_ci        }
5357db96d56Sopenharmony_ci
5367db96d56Sopenharmony_ci        if (keys->dk_kind == DICT_KEYS_GENERAL) {
5377db96d56Sopenharmony_ci            PyDictKeyEntry *entries = DK_ENTRIES(keys);
5387db96d56Sopenharmony_ci            for (Py_ssize_t i=0; i < usable; i++) {
5397db96d56Sopenharmony_ci                PyDictKeyEntry *entry = &entries[i];
5407db96d56Sopenharmony_ci                PyObject *key = entry->me_key;
5417db96d56Sopenharmony_ci
5427db96d56Sopenharmony_ci                if (key != NULL) {
5437db96d56Sopenharmony_ci                    /* test_dict fails if PyObject_Hash() is called again */
5447db96d56Sopenharmony_ci                    CHECK(entry->me_hash != -1);
5457db96d56Sopenharmony_ci                    CHECK(entry->me_value != NULL);
5467db96d56Sopenharmony_ci
5477db96d56Sopenharmony_ci                    if (PyUnicode_CheckExact(key)) {
5487db96d56Sopenharmony_ci                        Py_hash_t hash = unicode_get_hash(key);
5497db96d56Sopenharmony_ci                        CHECK(entry->me_hash == hash);
5507db96d56Sopenharmony_ci                    }
5517db96d56Sopenharmony_ci                }
5527db96d56Sopenharmony_ci            }
5537db96d56Sopenharmony_ci        }
5547db96d56Sopenharmony_ci        else {
5557db96d56Sopenharmony_ci            PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys);
5567db96d56Sopenharmony_ci            for (Py_ssize_t i=0; i < usable; i++) {
5577db96d56Sopenharmony_ci                PyDictUnicodeEntry *entry = &entries[i];
5587db96d56Sopenharmony_ci                PyObject *key = entry->me_key;
5597db96d56Sopenharmony_ci
5607db96d56Sopenharmony_ci                if (key != NULL) {
5617db96d56Sopenharmony_ci                    CHECK(PyUnicode_CheckExact(key));
5627db96d56Sopenharmony_ci                    Py_hash_t hash = unicode_get_hash(key);
5637db96d56Sopenharmony_ci                    CHECK(hash != -1);
5647db96d56Sopenharmony_ci                    if (!splitted) {
5657db96d56Sopenharmony_ci                        CHECK(entry->me_value != NULL);
5667db96d56Sopenharmony_ci                    }
5677db96d56Sopenharmony_ci                }
5687db96d56Sopenharmony_ci
5697db96d56Sopenharmony_ci                if (splitted) {
5707db96d56Sopenharmony_ci                    CHECK(entry->me_value == NULL);
5717db96d56Sopenharmony_ci                }
5727db96d56Sopenharmony_ci            }
5737db96d56Sopenharmony_ci        }
5747db96d56Sopenharmony_ci
5757db96d56Sopenharmony_ci        if (splitted) {
5767db96d56Sopenharmony_ci            CHECK(mp->ma_used <= SHARED_KEYS_MAX_SIZE);
5777db96d56Sopenharmony_ci            /* splitted table */
5787db96d56Sopenharmony_ci            int duplicate_check = 0;
5797db96d56Sopenharmony_ci            for (Py_ssize_t i=0; i < mp->ma_used; i++) {
5807db96d56Sopenharmony_ci                int index = get_index_from_order(mp, i);
5817db96d56Sopenharmony_ci                CHECK((duplicate_check & (1<<index)) == 0);
5827db96d56Sopenharmony_ci                duplicate_check |= (1<<index);
5837db96d56Sopenharmony_ci                CHECK(mp->ma_values->values[index] != NULL);
5847db96d56Sopenharmony_ci            }
5857db96d56Sopenharmony_ci        }
5867db96d56Sopenharmony_ci    }
5877db96d56Sopenharmony_ci    return 1;
5887db96d56Sopenharmony_ci
5897db96d56Sopenharmony_ci#undef CHECK
5907db96d56Sopenharmony_ci}
5917db96d56Sopenharmony_ci
5927db96d56Sopenharmony_ci
5937db96d56Sopenharmony_cistatic PyDictKeysObject*
5947db96d56Sopenharmony_cinew_keys_object(uint8_t log2_size, bool unicode)
5957db96d56Sopenharmony_ci{
5967db96d56Sopenharmony_ci    PyDictKeysObject *dk;
5977db96d56Sopenharmony_ci    Py_ssize_t usable;
5987db96d56Sopenharmony_ci    int log2_bytes;
5997db96d56Sopenharmony_ci    size_t entry_size = unicode ? sizeof(PyDictUnicodeEntry) : sizeof(PyDictKeyEntry);
6007db96d56Sopenharmony_ci
6017db96d56Sopenharmony_ci    assert(log2_size >= PyDict_LOG_MINSIZE);
6027db96d56Sopenharmony_ci
6037db96d56Sopenharmony_ci    usable = USABLE_FRACTION((size_t)1<<log2_size);
6047db96d56Sopenharmony_ci    if (log2_size < 8) {
6057db96d56Sopenharmony_ci        log2_bytes = log2_size;
6067db96d56Sopenharmony_ci    }
6077db96d56Sopenharmony_ci    else if (log2_size < 16) {
6087db96d56Sopenharmony_ci        log2_bytes = log2_size + 1;
6097db96d56Sopenharmony_ci    }
6107db96d56Sopenharmony_ci#if SIZEOF_VOID_P > 4
6117db96d56Sopenharmony_ci    else if (log2_size >= 32) {
6127db96d56Sopenharmony_ci        log2_bytes = log2_size + 3;
6137db96d56Sopenharmony_ci    }
6147db96d56Sopenharmony_ci#endif
6157db96d56Sopenharmony_ci    else {
6167db96d56Sopenharmony_ci        log2_bytes = log2_size + 2;
6177db96d56Sopenharmony_ci    }
6187db96d56Sopenharmony_ci
6197db96d56Sopenharmony_ci#if PyDict_MAXFREELIST > 0
6207db96d56Sopenharmony_ci    struct _Py_dict_state *state = get_dict_state();
6217db96d56Sopenharmony_ci#ifdef Py_DEBUG
6227db96d56Sopenharmony_ci    // new_keys_object() must not be called after _PyDict_Fini()
6237db96d56Sopenharmony_ci    assert(state->keys_numfree != -1);
6247db96d56Sopenharmony_ci#endif
6257db96d56Sopenharmony_ci    if (log2_size == PyDict_LOG_MINSIZE && unicode && state->keys_numfree > 0) {
6267db96d56Sopenharmony_ci        dk = state->keys_free_list[--state->keys_numfree];
6277db96d56Sopenharmony_ci        OBJECT_STAT_INC(from_freelist);
6287db96d56Sopenharmony_ci    }
6297db96d56Sopenharmony_ci    else
6307db96d56Sopenharmony_ci#endif
6317db96d56Sopenharmony_ci    {
6327db96d56Sopenharmony_ci        dk = PyObject_Malloc(sizeof(PyDictKeysObject)
6337db96d56Sopenharmony_ci                             + ((size_t)1 << log2_bytes)
6347db96d56Sopenharmony_ci                             + entry_size * usable);
6357db96d56Sopenharmony_ci        if (dk == NULL) {
6367db96d56Sopenharmony_ci            PyErr_NoMemory();
6377db96d56Sopenharmony_ci            return NULL;
6387db96d56Sopenharmony_ci        }
6397db96d56Sopenharmony_ci    }
6407db96d56Sopenharmony_ci#ifdef Py_REF_DEBUG
6417db96d56Sopenharmony_ci    _Py_RefTotal++;
6427db96d56Sopenharmony_ci#endif
6437db96d56Sopenharmony_ci    dk->dk_refcnt = 1;
6447db96d56Sopenharmony_ci    dk->dk_log2_size = log2_size;
6457db96d56Sopenharmony_ci    dk->dk_log2_index_bytes = log2_bytes;
6467db96d56Sopenharmony_ci    dk->dk_kind = unicode ? DICT_KEYS_UNICODE : DICT_KEYS_GENERAL;
6477db96d56Sopenharmony_ci    dk->dk_nentries = 0;
6487db96d56Sopenharmony_ci    dk->dk_usable = usable;
6497db96d56Sopenharmony_ci    dk->dk_version = 0;
6507db96d56Sopenharmony_ci    memset(&dk->dk_indices[0], 0xff, ((size_t)1 << log2_bytes));
6517db96d56Sopenharmony_ci    memset(&dk->dk_indices[(size_t)1 << log2_bytes], 0, entry_size * usable);
6527db96d56Sopenharmony_ci    return dk;
6537db96d56Sopenharmony_ci}
6547db96d56Sopenharmony_ci
6557db96d56Sopenharmony_cistatic void
6567db96d56Sopenharmony_cifree_keys_object(PyDictKeysObject *keys)
6577db96d56Sopenharmony_ci{
6587db96d56Sopenharmony_ci    assert(keys != Py_EMPTY_KEYS);
6597db96d56Sopenharmony_ci    if (DK_IS_UNICODE(keys)) {
6607db96d56Sopenharmony_ci        PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys);
6617db96d56Sopenharmony_ci        Py_ssize_t i, n;
6627db96d56Sopenharmony_ci        for (i = 0, n = keys->dk_nentries; i < n; i++) {
6637db96d56Sopenharmony_ci            Py_XDECREF(entries[i].me_key);
6647db96d56Sopenharmony_ci            Py_XDECREF(entries[i].me_value);
6657db96d56Sopenharmony_ci        }
6667db96d56Sopenharmony_ci    }
6677db96d56Sopenharmony_ci    else {
6687db96d56Sopenharmony_ci        PyDictKeyEntry *entries = DK_ENTRIES(keys);
6697db96d56Sopenharmony_ci        Py_ssize_t i, n;
6707db96d56Sopenharmony_ci        for (i = 0, n = keys->dk_nentries; i < n; i++) {
6717db96d56Sopenharmony_ci            Py_XDECREF(entries[i].me_key);
6727db96d56Sopenharmony_ci            Py_XDECREF(entries[i].me_value);
6737db96d56Sopenharmony_ci        }
6747db96d56Sopenharmony_ci    }
6757db96d56Sopenharmony_ci#if PyDict_MAXFREELIST > 0
6767db96d56Sopenharmony_ci    struct _Py_dict_state *state = get_dict_state();
6777db96d56Sopenharmony_ci#ifdef Py_DEBUG
6787db96d56Sopenharmony_ci    // free_keys_object() must not be called after _PyDict_Fini()
6797db96d56Sopenharmony_ci    assert(state->keys_numfree != -1);
6807db96d56Sopenharmony_ci#endif
6817db96d56Sopenharmony_ci    if (DK_LOG_SIZE(keys) == PyDict_LOG_MINSIZE
6827db96d56Sopenharmony_ci            && state->keys_numfree < PyDict_MAXFREELIST
6837db96d56Sopenharmony_ci            && DK_IS_UNICODE(keys)) {
6847db96d56Sopenharmony_ci        state->keys_free_list[state->keys_numfree++] = keys;
6857db96d56Sopenharmony_ci        OBJECT_STAT_INC(to_freelist);
6867db96d56Sopenharmony_ci        return;
6877db96d56Sopenharmony_ci    }
6887db96d56Sopenharmony_ci#endif
6897db96d56Sopenharmony_ci    PyObject_Free(keys);
6907db96d56Sopenharmony_ci}
6917db96d56Sopenharmony_ci
6927db96d56Sopenharmony_cistatic inline PyDictValues*
6937db96d56Sopenharmony_cinew_values(Py_ssize_t size)
6947db96d56Sopenharmony_ci{
6957db96d56Sopenharmony_ci    assert(size > 0);
6967db96d56Sopenharmony_ci    size_t prefix_size = _Py_SIZE_ROUND_UP(size+2, sizeof(PyObject *));
6977db96d56Sopenharmony_ci    assert(prefix_size < 256);
6987db96d56Sopenharmony_ci    size_t n = prefix_size + size * sizeof(PyObject *);
6997db96d56Sopenharmony_ci    uint8_t *mem = PyMem_Malloc(n);
7007db96d56Sopenharmony_ci    if (mem == NULL) {
7017db96d56Sopenharmony_ci        return NULL;
7027db96d56Sopenharmony_ci    }
7037db96d56Sopenharmony_ci    assert(prefix_size % sizeof(PyObject *) == 0);
7047db96d56Sopenharmony_ci    mem[prefix_size-1] = (uint8_t)prefix_size;
7057db96d56Sopenharmony_ci    return (PyDictValues*)(mem + prefix_size);
7067db96d56Sopenharmony_ci}
7077db96d56Sopenharmony_ci
7087db96d56Sopenharmony_cistatic inline void
7097db96d56Sopenharmony_cifree_values(PyDictValues *values)
7107db96d56Sopenharmony_ci{
7117db96d56Sopenharmony_ci    int prefix_size = ((uint8_t *)values)[-1];
7127db96d56Sopenharmony_ci    PyMem_Free(((char *)values)-prefix_size);
7137db96d56Sopenharmony_ci}
7147db96d56Sopenharmony_ci
7157db96d56Sopenharmony_ci/* Consumes a reference to the keys object */
7167db96d56Sopenharmony_cistatic PyObject *
7177db96d56Sopenharmony_cinew_dict(PyDictKeysObject *keys, PyDictValues *values, Py_ssize_t used, int free_values_on_failure)
7187db96d56Sopenharmony_ci{
7197db96d56Sopenharmony_ci    PyDictObject *mp;
7207db96d56Sopenharmony_ci    assert(keys != NULL);
7217db96d56Sopenharmony_ci#if PyDict_MAXFREELIST > 0
7227db96d56Sopenharmony_ci    struct _Py_dict_state *state = get_dict_state();
7237db96d56Sopenharmony_ci#ifdef Py_DEBUG
7247db96d56Sopenharmony_ci    // new_dict() must not be called after _PyDict_Fini()
7257db96d56Sopenharmony_ci    assert(state->numfree != -1);
7267db96d56Sopenharmony_ci#endif
7277db96d56Sopenharmony_ci    if (state->numfree) {
7287db96d56Sopenharmony_ci        mp = state->free_list[--state->numfree];
7297db96d56Sopenharmony_ci        assert (mp != NULL);
7307db96d56Sopenharmony_ci        assert (Py_IS_TYPE(mp, &PyDict_Type));
7317db96d56Sopenharmony_ci        OBJECT_STAT_INC(from_freelist);
7327db96d56Sopenharmony_ci        _Py_NewReference((PyObject *)mp);
7337db96d56Sopenharmony_ci    }
7347db96d56Sopenharmony_ci    else
7357db96d56Sopenharmony_ci#endif
7367db96d56Sopenharmony_ci    {
7377db96d56Sopenharmony_ci        mp = PyObject_GC_New(PyDictObject, &PyDict_Type);
7387db96d56Sopenharmony_ci        if (mp == NULL) {
7397db96d56Sopenharmony_ci            dictkeys_decref(keys);
7407db96d56Sopenharmony_ci            if (free_values_on_failure) {
7417db96d56Sopenharmony_ci                free_values(values);
7427db96d56Sopenharmony_ci            }
7437db96d56Sopenharmony_ci            return NULL;
7447db96d56Sopenharmony_ci        }
7457db96d56Sopenharmony_ci    }
7467db96d56Sopenharmony_ci    mp->ma_keys = keys;
7477db96d56Sopenharmony_ci    mp->ma_values = values;
7487db96d56Sopenharmony_ci    mp->ma_used = used;
7497db96d56Sopenharmony_ci    mp->ma_version_tag = DICT_NEXT_VERSION();
7507db96d56Sopenharmony_ci    ASSERT_CONSISTENT(mp);
7517db96d56Sopenharmony_ci    return (PyObject *)mp;
7527db96d56Sopenharmony_ci}
7537db96d56Sopenharmony_ci
7547db96d56Sopenharmony_cistatic inline Py_ssize_t
7557db96d56Sopenharmony_cishared_keys_usable_size(PyDictKeysObject *keys)
7567db96d56Sopenharmony_ci{
7577db96d56Sopenharmony_ci    return keys->dk_nentries + keys->dk_usable;
7587db96d56Sopenharmony_ci}
7597db96d56Sopenharmony_ci
7607db96d56Sopenharmony_ci/* Consumes a reference to the keys object */
7617db96d56Sopenharmony_cistatic PyObject *
7627db96d56Sopenharmony_cinew_dict_with_shared_keys(PyDictKeysObject *keys)
7637db96d56Sopenharmony_ci{
7647db96d56Sopenharmony_ci    PyDictValues *values;
7657db96d56Sopenharmony_ci    Py_ssize_t i, size;
7667db96d56Sopenharmony_ci
7677db96d56Sopenharmony_ci    size = shared_keys_usable_size(keys);
7687db96d56Sopenharmony_ci    values = new_values(size);
7697db96d56Sopenharmony_ci    if (values == NULL) {
7707db96d56Sopenharmony_ci        dictkeys_decref(keys);
7717db96d56Sopenharmony_ci        return PyErr_NoMemory();
7727db96d56Sopenharmony_ci    }
7737db96d56Sopenharmony_ci    ((char *)values)[-2] = 0;
7747db96d56Sopenharmony_ci    for (i = 0; i < size; i++) {
7757db96d56Sopenharmony_ci        values->values[i] = NULL;
7767db96d56Sopenharmony_ci    }
7777db96d56Sopenharmony_ci    return new_dict(keys, values, 0, 1);
7787db96d56Sopenharmony_ci}
7797db96d56Sopenharmony_ci
7807db96d56Sopenharmony_ci
7817db96d56Sopenharmony_cistatic PyDictKeysObject *
7827db96d56Sopenharmony_ciclone_combined_dict_keys(PyDictObject *orig)
7837db96d56Sopenharmony_ci{
7847db96d56Sopenharmony_ci    assert(PyDict_Check(orig));
7857db96d56Sopenharmony_ci    assert(Py_TYPE(orig)->tp_iter == (getiterfunc)dict_iter);
7867db96d56Sopenharmony_ci    assert(orig->ma_values == NULL);
7877db96d56Sopenharmony_ci    assert(orig->ma_keys->dk_refcnt == 1);
7887db96d56Sopenharmony_ci
7897db96d56Sopenharmony_ci    Py_ssize_t keys_size = _PyDict_KeysSize(orig->ma_keys);
7907db96d56Sopenharmony_ci    PyDictKeysObject *keys = PyObject_Malloc(keys_size);
7917db96d56Sopenharmony_ci    if (keys == NULL) {
7927db96d56Sopenharmony_ci        PyErr_NoMemory();
7937db96d56Sopenharmony_ci        return NULL;
7947db96d56Sopenharmony_ci    }
7957db96d56Sopenharmony_ci
7967db96d56Sopenharmony_ci    memcpy(keys, orig->ma_keys, keys_size);
7977db96d56Sopenharmony_ci
7987db96d56Sopenharmony_ci    /* After copying key/value pairs, we need to incref all
7997db96d56Sopenharmony_ci       keys and values and they are about to be co-owned by a
8007db96d56Sopenharmony_ci       new dict object. */
8017db96d56Sopenharmony_ci    PyObject **pkey, **pvalue;
8027db96d56Sopenharmony_ci    size_t offs;
8037db96d56Sopenharmony_ci    if (DK_IS_UNICODE(orig->ma_keys)) {
8047db96d56Sopenharmony_ci        PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(keys);
8057db96d56Sopenharmony_ci        pkey = &ep0->me_key;
8067db96d56Sopenharmony_ci        pvalue = &ep0->me_value;
8077db96d56Sopenharmony_ci        offs = sizeof(PyDictUnicodeEntry) / sizeof(PyObject*);
8087db96d56Sopenharmony_ci    }
8097db96d56Sopenharmony_ci    else {
8107db96d56Sopenharmony_ci        PyDictKeyEntry *ep0 = DK_ENTRIES(keys);
8117db96d56Sopenharmony_ci        pkey = &ep0->me_key;
8127db96d56Sopenharmony_ci        pvalue = &ep0->me_value;
8137db96d56Sopenharmony_ci        offs = sizeof(PyDictKeyEntry) / sizeof(PyObject*);
8147db96d56Sopenharmony_ci    }
8157db96d56Sopenharmony_ci
8167db96d56Sopenharmony_ci    Py_ssize_t n = keys->dk_nentries;
8177db96d56Sopenharmony_ci    for (Py_ssize_t i = 0; i < n; i++) {
8187db96d56Sopenharmony_ci        PyObject *value = *pvalue;
8197db96d56Sopenharmony_ci        if (value != NULL) {
8207db96d56Sopenharmony_ci            Py_INCREF(value);
8217db96d56Sopenharmony_ci            Py_INCREF(*pkey);
8227db96d56Sopenharmony_ci        }
8237db96d56Sopenharmony_ci        pvalue += offs;
8247db96d56Sopenharmony_ci        pkey += offs;
8257db96d56Sopenharmony_ci    }
8267db96d56Sopenharmony_ci
8277db96d56Sopenharmony_ci    /* Since we copied the keys table we now have an extra reference
8287db96d56Sopenharmony_ci       in the system.  Manually call increment _Py_RefTotal to signal that
8297db96d56Sopenharmony_ci       we have it now; calling dictkeys_incref would be an error as
8307db96d56Sopenharmony_ci       keys->dk_refcnt is already set to 1 (after memcpy). */
8317db96d56Sopenharmony_ci#ifdef Py_REF_DEBUG
8327db96d56Sopenharmony_ci    _Py_RefTotal++;
8337db96d56Sopenharmony_ci#endif
8347db96d56Sopenharmony_ci    return keys;
8357db96d56Sopenharmony_ci}
8367db96d56Sopenharmony_ci
8377db96d56Sopenharmony_ciPyObject *
8387db96d56Sopenharmony_ciPyDict_New(void)
8397db96d56Sopenharmony_ci{
8407db96d56Sopenharmony_ci    dictkeys_incref(Py_EMPTY_KEYS);
8417db96d56Sopenharmony_ci    return new_dict(Py_EMPTY_KEYS, NULL, 0, 0);
8427db96d56Sopenharmony_ci}
8437db96d56Sopenharmony_ci
8447db96d56Sopenharmony_ci/* Search index of hash table from offset of entry table */
8457db96d56Sopenharmony_cistatic Py_ssize_t
8467db96d56Sopenharmony_cilookdict_index(PyDictKeysObject *k, Py_hash_t hash, Py_ssize_t index)
8477db96d56Sopenharmony_ci{
8487db96d56Sopenharmony_ci    size_t mask = DK_MASK(k);
8497db96d56Sopenharmony_ci    size_t perturb = (size_t)hash;
8507db96d56Sopenharmony_ci    size_t i = (size_t)hash & mask;
8517db96d56Sopenharmony_ci
8527db96d56Sopenharmony_ci    for (;;) {
8537db96d56Sopenharmony_ci        Py_ssize_t ix = dictkeys_get_index(k, i);
8547db96d56Sopenharmony_ci        if (ix == index) {
8557db96d56Sopenharmony_ci            return i;
8567db96d56Sopenharmony_ci        }
8577db96d56Sopenharmony_ci        if (ix == DKIX_EMPTY) {
8587db96d56Sopenharmony_ci            return DKIX_EMPTY;
8597db96d56Sopenharmony_ci        }
8607db96d56Sopenharmony_ci        perturb >>= PERTURB_SHIFT;
8617db96d56Sopenharmony_ci        i = mask & (i*5 + perturb + 1);
8627db96d56Sopenharmony_ci    }
8637db96d56Sopenharmony_ci    Py_UNREACHABLE();
8647db96d56Sopenharmony_ci}
8657db96d56Sopenharmony_ci
8667db96d56Sopenharmony_ci// Search non-Unicode key from Unicode table
8677db96d56Sopenharmony_cistatic Py_ssize_t
8687db96d56Sopenharmony_ciunicodekeys_lookup_generic(PyDictObject *mp, PyDictKeysObject* dk, PyObject *key, Py_hash_t hash)
8697db96d56Sopenharmony_ci{
8707db96d56Sopenharmony_ci    PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(dk);
8717db96d56Sopenharmony_ci    size_t mask = DK_MASK(dk);
8727db96d56Sopenharmony_ci    size_t perturb = hash;
8737db96d56Sopenharmony_ci    size_t i = (size_t)hash & mask;
8747db96d56Sopenharmony_ci    Py_ssize_t ix;
8757db96d56Sopenharmony_ci    for (;;) {
8767db96d56Sopenharmony_ci        ix = dictkeys_get_index(dk, i);
8777db96d56Sopenharmony_ci        if (ix >= 0) {
8787db96d56Sopenharmony_ci            PyDictUnicodeEntry *ep = &ep0[ix];
8797db96d56Sopenharmony_ci            assert(ep->me_key != NULL);
8807db96d56Sopenharmony_ci            assert(PyUnicode_CheckExact(ep->me_key));
8817db96d56Sopenharmony_ci            if (ep->me_key == key) {
8827db96d56Sopenharmony_ci                return ix;
8837db96d56Sopenharmony_ci            }
8847db96d56Sopenharmony_ci            if (unicode_get_hash(ep->me_key) == hash) {
8857db96d56Sopenharmony_ci                PyObject *startkey = ep->me_key;
8867db96d56Sopenharmony_ci                Py_INCREF(startkey);
8877db96d56Sopenharmony_ci                int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
8887db96d56Sopenharmony_ci                Py_DECREF(startkey);
8897db96d56Sopenharmony_ci                if (cmp < 0) {
8907db96d56Sopenharmony_ci                    return DKIX_ERROR;
8917db96d56Sopenharmony_ci                }
8927db96d56Sopenharmony_ci                if (dk == mp->ma_keys && ep->me_key == startkey) {
8937db96d56Sopenharmony_ci                    if (cmp > 0) {
8947db96d56Sopenharmony_ci                        return ix;
8957db96d56Sopenharmony_ci                    }
8967db96d56Sopenharmony_ci                }
8977db96d56Sopenharmony_ci                else {
8987db96d56Sopenharmony_ci                    /* The dict was mutated, restart */
8997db96d56Sopenharmony_ci                    return DKIX_KEY_CHANGED;
9007db96d56Sopenharmony_ci                }
9017db96d56Sopenharmony_ci            }
9027db96d56Sopenharmony_ci        }
9037db96d56Sopenharmony_ci        else if (ix == DKIX_EMPTY) {
9047db96d56Sopenharmony_ci            return DKIX_EMPTY;
9057db96d56Sopenharmony_ci        }
9067db96d56Sopenharmony_ci        perturb >>= PERTURB_SHIFT;
9077db96d56Sopenharmony_ci        i = mask & (i*5 + perturb + 1);
9087db96d56Sopenharmony_ci    }
9097db96d56Sopenharmony_ci    Py_UNREACHABLE();
9107db96d56Sopenharmony_ci}
9117db96d56Sopenharmony_ci
9127db96d56Sopenharmony_ci// Search Unicode key from Unicode table.
9137db96d56Sopenharmony_cistatic Py_ssize_t _Py_HOT_FUNCTION
9147db96d56Sopenharmony_ciunicodekeys_lookup_unicode(PyDictKeysObject* dk, PyObject *key, Py_hash_t hash)
9157db96d56Sopenharmony_ci{
9167db96d56Sopenharmony_ci    PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(dk);
9177db96d56Sopenharmony_ci    size_t mask = DK_MASK(dk);
9187db96d56Sopenharmony_ci    size_t perturb = hash;
9197db96d56Sopenharmony_ci    size_t i = (size_t)hash & mask;
9207db96d56Sopenharmony_ci    Py_ssize_t ix;
9217db96d56Sopenharmony_ci    for (;;) {
9227db96d56Sopenharmony_ci        ix = dictkeys_get_index(dk, i);
9237db96d56Sopenharmony_ci        if (ix >= 0) {
9247db96d56Sopenharmony_ci            PyDictUnicodeEntry *ep = &ep0[ix];
9257db96d56Sopenharmony_ci            assert(ep->me_key != NULL);
9267db96d56Sopenharmony_ci            assert(PyUnicode_CheckExact(ep->me_key));
9277db96d56Sopenharmony_ci            if (ep->me_key == key ||
9287db96d56Sopenharmony_ci                    (unicode_get_hash(ep->me_key) == hash && unicode_eq(ep->me_key, key))) {
9297db96d56Sopenharmony_ci                return ix;
9307db96d56Sopenharmony_ci            }
9317db96d56Sopenharmony_ci        }
9327db96d56Sopenharmony_ci        else if (ix == DKIX_EMPTY) {
9337db96d56Sopenharmony_ci            return DKIX_EMPTY;
9347db96d56Sopenharmony_ci        }
9357db96d56Sopenharmony_ci        perturb >>= PERTURB_SHIFT;
9367db96d56Sopenharmony_ci        i = mask & (i*5 + perturb + 1);
9377db96d56Sopenharmony_ci        ix = dictkeys_get_index(dk, i);
9387db96d56Sopenharmony_ci        if (ix >= 0) {
9397db96d56Sopenharmony_ci            PyDictUnicodeEntry *ep = &ep0[ix];
9407db96d56Sopenharmony_ci            assert(ep->me_key != NULL);
9417db96d56Sopenharmony_ci            assert(PyUnicode_CheckExact(ep->me_key));
9427db96d56Sopenharmony_ci            if (ep->me_key == key ||
9437db96d56Sopenharmony_ci                    (unicode_get_hash(ep->me_key) == hash && unicode_eq(ep->me_key, key))) {
9447db96d56Sopenharmony_ci                return ix;
9457db96d56Sopenharmony_ci            }
9467db96d56Sopenharmony_ci        }
9477db96d56Sopenharmony_ci        else if (ix == DKIX_EMPTY) {
9487db96d56Sopenharmony_ci            return DKIX_EMPTY;
9497db96d56Sopenharmony_ci        }
9507db96d56Sopenharmony_ci        perturb >>= PERTURB_SHIFT;
9517db96d56Sopenharmony_ci        i = mask & (i*5 + perturb + 1);
9527db96d56Sopenharmony_ci    }
9537db96d56Sopenharmony_ci    Py_UNREACHABLE();
9547db96d56Sopenharmony_ci}
9557db96d56Sopenharmony_ci
9567db96d56Sopenharmony_ci// Search key from Generic table.
9577db96d56Sopenharmony_cistatic Py_ssize_t
9587db96d56Sopenharmony_cidictkeys_generic_lookup(PyDictObject *mp, PyDictKeysObject* dk, PyObject *key, Py_hash_t hash)
9597db96d56Sopenharmony_ci{
9607db96d56Sopenharmony_ci    PyDictKeyEntry *ep0 = DK_ENTRIES(dk);
9617db96d56Sopenharmony_ci    size_t mask = DK_MASK(dk);
9627db96d56Sopenharmony_ci    size_t perturb = hash;
9637db96d56Sopenharmony_ci    size_t i = (size_t)hash & mask;
9647db96d56Sopenharmony_ci    Py_ssize_t ix;
9657db96d56Sopenharmony_ci    for (;;) {
9667db96d56Sopenharmony_ci        ix = dictkeys_get_index(dk, i);
9677db96d56Sopenharmony_ci        if (ix >= 0) {
9687db96d56Sopenharmony_ci            PyDictKeyEntry *ep = &ep0[ix];
9697db96d56Sopenharmony_ci            assert(ep->me_key != NULL);
9707db96d56Sopenharmony_ci            if (ep->me_key == key) {
9717db96d56Sopenharmony_ci                return ix;
9727db96d56Sopenharmony_ci            }
9737db96d56Sopenharmony_ci            if (ep->me_hash == hash) {
9747db96d56Sopenharmony_ci                PyObject *startkey = ep->me_key;
9757db96d56Sopenharmony_ci                Py_INCREF(startkey);
9767db96d56Sopenharmony_ci                int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
9777db96d56Sopenharmony_ci                Py_DECREF(startkey);
9787db96d56Sopenharmony_ci                if (cmp < 0) {
9797db96d56Sopenharmony_ci                    return DKIX_ERROR;
9807db96d56Sopenharmony_ci                }
9817db96d56Sopenharmony_ci                if (dk == mp->ma_keys && ep->me_key == startkey) {
9827db96d56Sopenharmony_ci                    if (cmp > 0) {
9837db96d56Sopenharmony_ci                        return ix;
9847db96d56Sopenharmony_ci                    }
9857db96d56Sopenharmony_ci                }
9867db96d56Sopenharmony_ci                else {
9877db96d56Sopenharmony_ci                    /* The dict was mutated, restart */
9887db96d56Sopenharmony_ci                    return DKIX_KEY_CHANGED;
9897db96d56Sopenharmony_ci                }
9907db96d56Sopenharmony_ci            }
9917db96d56Sopenharmony_ci        }
9927db96d56Sopenharmony_ci        else if (ix == DKIX_EMPTY) {
9937db96d56Sopenharmony_ci            return DKIX_EMPTY;
9947db96d56Sopenharmony_ci        }
9957db96d56Sopenharmony_ci        perturb >>= PERTURB_SHIFT;
9967db96d56Sopenharmony_ci        i = mask & (i*5 + perturb + 1);
9977db96d56Sopenharmony_ci    }
9987db96d56Sopenharmony_ci    Py_UNREACHABLE();
9997db96d56Sopenharmony_ci}
10007db96d56Sopenharmony_ci
10017db96d56Sopenharmony_ci/* Lookup a string in a (all unicode) dict keys.
10027db96d56Sopenharmony_ci * Returns DKIX_ERROR if key is not a string,
10037db96d56Sopenharmony_ci * or if the dict keys is not all strings.
10047db96d56Sopenharmony_ci * If the keys is present then return the index of key.
10057db96d56Sopenharmony_ci * If the key is not present then return DKIX_EMPTY.
10067db96d56Sopenharmony_ci */
10077db96d56Sopenharmony_ciPy_ssize_t
10087db96d56Sopenharmony_ci_PyDictKeys_StringLookup(PyDictKeysObject* dk, PyObject *key)
10097db96d56Sopenharmony_ci{
10107db96d56Sopenharmony_ci    DictKeysKind kind = dk->dk_kind;
10117db96d56Sopenharmony_ci    if (!PyUnicode_CheckExact(key) || kind == DICT_KEYS_GENERAL) {
10127db96d56Sopenharmony_ci        return DKIX_ERROR;
10137db96d56Sopenharmony_ci    }
10147db96d56Sopenharmony_ci    Py_hash_t hash = unicode_get_hash(key);
10157db96d56Sopenharmony_ci    if (hash == -1) {
10167db96d56Sopenharmony_ci        hash = PyUnicode_Type.tp_hash(key);
10177db96d56Sopenharmony_ci        if (hash == -1) {
10187db96d56Sopenharmony_ci            PyErr_Clear();
10197db96d56Sopenharmony_ci            return DKIX_ERROR;
10207db96d56Sopenharmony_ci        }
10217db96d56Sopenharmony_ci    }
10227db96d56Sopenharmony_ci    return unicodekeys_lookup_unicode(dk, key, hash);
10237db96d56Sopenharmony_ci}
10247db96d56Sopenharmony_ci
10257db96d56Sopenharmony_ci/*
10267db96d56Sopenharmony_ciThe basic lookup function used by all operations.
10277db96d56Sopenharmony_ciThis is based on Algorithm D from Knuth Vol. 3, Sec. 6.4.
10287db96d56Sopenharmony_ciOpen addressing is preferred over chaining since the link overhead for
10297db96d56Sopenharmony_cichaining would be substantial (100% with typical malloc overhead).
10307db96d56Sopenharmony_ci
10317db96d56Sopenharmony_ciThe initial probe index is computed as hash mod the table size. Subsequent
10327db96d56Sopenharmony_ciprobe indices are computed as explained earlier.
10337db96d56Sopenharmony_ci
10347db96d56Sopenharmony_ciAll arithmetic on hash should ignore overflow.
10357db96d56Sopenharmony_ci
10367db96d56Sopenharmony_ci_Py_dict_lookup() is general-purpose, and may return DKIX_ERROR if (and only if) a
10377db96d56Sopenharmony_cicomparison raises an exception.
10387db96d56Sopenharmony_ciWhen the key isn't found a DKIX_EMPTY is returned.
10397db96d56Sopenharmony_ci*/
10407db96d56Sopenharmony_ciPy_ssize_t
10417db96d56Sopenharmony_ci_Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr)
10427db96d56Sopenharmony_ci{
10437db96d56Sopenharmony_ci    PyDictKeysObject *dk;
10447db96d56Sopenharmony_ci    DictKeysKind kind;
10457db96d56Sopenharmony_ci    Py_ssize_t ix;
10467db96d56Sopenharmony_ci
10477db96d56Sopenharmony_cistart:
10487db96d56Sopenharmony_ci    dk = mp->ma_keys;
10497db96d56Sopenharmony_ci    kind = dk->dk_kind;
10507db96d56Sopenharmony_ci
10517db96d56Sopenharmony_ci    if (kind != DICT_KEYS_GENERAL) {
10527db96d56Sopenharmony_ci        if (PyUnicode_CheckExact(key)) {
10537db96d56Sopenharmony_ci            ix = unicodekeys_lookup_unicode(dk, key, hash);
10547db96d56Sopenharmony_ci        }
10557db96d56Sopenharmony_ci        else {
10567db96d56Sopenharmony_ci            ix = unicodekeys_lookup_generic(mp, dk, key, hash);
10577db96d56Sopenharmony_ci            if (ix == DKIX_KEY_CHANGED) {
10587db96d56Sopenharmony_ci                goto start;
10597db96d56Sopenharmony_ci            }
10607db96d56Sopenharmony_ci        }
10617db96d56Sopenharmony_ci
10627db96d56Sopenharmony_ci        if (ix >= 0) {
10637db96d56Sopenharmony_ci            if (kind == DICT_KEYS_SPLIT) {
10647db96d56Sopenharmony_ci                *value_addr = mp->ma_values->values[ix];
10657db96d56Sopenharmony_ci            }
10667db96d56Sopenharmony_ci            else {
10677db96d56Sopenharmony_ci                *value_addr = DK_UNICODE_ENTRIES(dk)[ix].me_value;
10687db96d56Sopenharmony_ci            }
10697db96d56Sopenharmony_ci        }
10707db96d56Sopenharmony_ci        else {
10717db96d56Sopenharmony_ci            *value_addr = NULL;
10727db96d56Sopenharmony_ci        }
10737db96d56Sopenharmony_ci    }
10747db96d56Sopenharmony_ci    else {
10757db96d56Sopenharmony_ci        ix = dictkeys_generic_lookup(mp, dk, key, hash);
10767db96d56Sopenharmony_ci        if (ix == DKIX_KEY_CHANGED) {
10777db96d56Sopenharmony_ci            goto start;
10787db96d56Sopenharmony_ci        }
10797db96d56Sopenharmony_ci        if (ix >= 0) {
10807db96d56Sopenharmony_ci            *value_addr = DK_ENTRIES(dk)[ix].me_value;
10817db96d56Sopenharmony_ci        }
10827db96d56Sopenharmony_ci        else {
10837db96d56Sopenharmony_ci            *value_addr = NULL;
10847db96d56Sopenharmony_ci        }
10857db96d56Sopenharmony_ci    }
10867db96d56Sopenharmony_ci
10877db96d56Sopenharmony_ci    return ix;
10887db96d56Sopenharmony_ci}
10897db96d56Sopenharmony_ci
10907db96d56Sopenharmony_ciint
10917db96d56Sopenharmony_ci_PyDict_HasOnlyStringKeys(PyObject *dict)
10927db96d56Sopenharmony_ci{
10937db96d56Sopenharmony_ci    Py_ssize_t pos = 0;
10947db96d56Sopenharmony_ci    PyObject *key, *value;
10957db96d56Sopenharmony_ci    assert(PyDict_Check(dict));
10967db96d56Sopenharmony_ci    /* Shortcut */
10977db96d56Sopenharmony_ci    if (((PyDictObject *)dict)->ma_keys->dk_kind != DICT_KEYS_GENERAL)
10987db96d56Sopenharmony_ci        return 1;
10997db96d56Sopenharmony_ci    while (PyDict_Next(dict, &pos, &key, &value))
11007db96d56Sopenharmony_ci        if (!PyUnicode_Check(key))
11017db96d56Sopenharmony_ci            return 0;
11027db96d56Sopenharmony_ci    return 1;
11037db96d56Sopenharmony_ci}
11047db96d56Sopenharmony_ci
11057db96d56Sopenharmony_ci#define MAINTAIN_TRACKING(mp, key, value) \
11067db96d56Sopenharmony_ci    do { \
11077db96d56Sopenharmony_ci        if (!_PyObject_GC_IS_TRACKED(mp)) { \
11087db96d56Sopenharmony_ci            if (_PyObject_GC_MAY_BE_TRACKED(key) || \
11097db96d56Sopenharmony_ci                _PyObject_GC_MAY_BE_TRACKED(value)) { \
11107db96d56Sopenharmony_ci                _PyObject_GC_TRACK(mp); \
11117db96d56Sopenharmony_ci            } \
11127db96d56Sopenharmony_ci        } \
11137db96d56Sopenharmony_ci    } while(0)
11147db96d56Sopenharmony_ci
11157db96d56Sopenharmony_civoid
11167db96d56Sopenharmony_ci_PyDict_MaybeUntrack(PyObject *op)
11177db96d56Sopenharmony_ci{
11187db96d56Sopenharmony_ci    PyDictObject *mp;
11197db96d56Sopenharmony_ci    PyObject *value;
11207db96d56Sopenharmony_ci    Py_ssize_t i, numentries;
11217db96d56Sopenharmony_ci
11227db96d56Sopenharmony_ci    if (!PyDict_CheckExact(op) || !_PyObject_GC_IS_TRACKED(op))
11237db96d56Sopenharmony_ci        return;
11247db96d56Sopenharmony_ci
11257db96d56Sopenharmony_ci    mp = (PyDictObject *) op;
11267db96d56Sopenharmony_ci    numentries = mp->ma_keys->dk_nentries;
11277db96d56Sopenharmony_ci    if (_PyDict_HasSplitTable(mp)) {
11287db96d56Sopenharmony_ci        for (i = 0; i < numentries; i++) {
11297db96d56Sopenharmony_ci            if ((value = mp->ma_values->values[i]) == NULL)
11307db96d56Sopenharmony_ci                continue;
11317db96d56Sopenharmony_ci            if (_PyObject_GC_MAY_BE_TRACKED(value)) {
11327db96d56Sopenharmony_ci                return;
11337db96d56Sopenharmony_ci            }
11347db96d56Sopenharmony_ci        }
11357db96d56Sopenharmony_ci    }
11367db96d56Sopenharmony_ci    else {
11377db96d56Sopenharmony_ci        if (DK_IS_UNICODE(mp->ma_keys)) {
11387db96d56Sopenharmony_ci            PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(mp->ma_keys);
11397db96d56Sopenharmony_ci            for (i = 0; i < numentries; i++) {
11407db96d56Sopenharmony_ci                if ((value = ep0[i].me_value) == NULL)
11417db96d56Sopenharmony_ci                    continue;
11427db96d56Sopenharmony_ci                if (_PyObject_GC_MAY_BE_TRACKED(value))
11437db96d56Sopenharmony_ci                    return;
11447db96d56Sopenharmony_ci            }
11457db96d56Sopenharmony_ci        }
11467db96d56Sopenharmony_ci        else {
11477db96d56Sopenharmony_ci            PyDictKeyEntry *ep0 = DK_ENTRIES(mp->ma_keys);
11487db96d56Sopenharmony_ci            for (i = 0; i < numentries; i++) {
11497db96d56Sopenharmony_ci                if ((value = ep0[i].me_value) == NULL)
11507db96d56Sopenharmony_ci                    continue;
11517db96d56Sopenharmony_ci                if (_PyObject_GC_MAY_BE_TRACKED(value) ||
11527db96d56Sopenharmony_ci                    _PyObject_GC_MAY_BE_TRACKED(ep0[i].me_key))
11537db96d56Sopenharmony_ci                    return;
11547db96d56Sopenharmony_ci            }
11557db96d56Sopenharmony_ci        }
11567db96d56Sopenharmony_ci    }
11577db96d56Sopenharmony_ci    _PyObject_GC_UNTRACK(op);
11587db96d56Sopenharmony_ci}
11597db96d56Sopenharmony_ci
11607db96d56Sopenharmony_ci/* Internal function to find slot for an item from its hash
11617db96d56Sopenharmony_ci   when it is known that the key is not present in the dict.
11627db96d56Sopenharmony_ci
11637db96d56Sopenharmony_ci   The dict must be combined. */
11647db96d56Sopenharmony_cistatic Py_ssize_t
11657db96d56Sopenharmony_cifind_empty_slot(PyDictKeysObject *keys, Py_hash_t hash)
11667db96d56Sopenharmony_ci{
11677db96d56Sopenharmony_ci    assert(keys != NULL);
11687db96d56Sopenharmony_ci
11697db96d56Sopenharmony_ci    const size_t mask = DK_MASK(keys);
11707db96d56Sopenharmony_ci    size_t i = hash & mask;
11717db96d56Sopenharmony_ci    Py_ssize_t ix = dictkeys_get_index(keys, i);
11727db96d56Sopenharmony_ci    for (size_t perturb = hash; ix >= 0;) {
11737db96d56Sopenharmony_ci        perturb >>= PERTURB_SHIFT;
11747db96d56Sopenharmony_ci        i = (i*5 + perturb + 1) & mask;
11757db96d56Sopenharmony_ci        ix = dictkeys_get_index(keys, i);
11767db96d56Sopenharmony_ci    }
11777db96d56Sopenharmony_ci    return i;
11787db96d56Sopenharmony_ci}
11797db96d56Sopenharmony_ci
11807db96d56Sopenharmony_cistatic int
11817db96d56Sopenharmony_ciinsertion_resize(PyDictObject *mp, int unicode)
11827db96d56Sopenharmony_ci{
11837db96d56Sopenharmony_ci    return dictresize(mp, calculate_log2_keysize(GROWTH_RATE(mp)), unicode);
11847db96d56Sopenharmony_ci}
11857db96d56Sopenharmony_ci
11867db96d56Sopenharmony_cistatic Py_ssize_t
11877db96d56Sopenharmony_ciinsert_into_dictkeys(PyDictKeysObject *keys, PyObject *name)
11887db96d56Sopenharmony_ci{
11897db96d56Sopenharmony_ci    assert(PyUnicode_CheckExact(name));
11907db96d56Sopenharmony_ci    Py_hash_t hash = unicode_get_hash(name);
11917db96d56Sopenharmony_ci    if (hash == -1) {
11927db96d56Sopenharmony_ci        hash = PyUnicode_Type.tp_hash(name);
11937db96d56Sopenharmony_ci        if (hash == -1) {
11947db96d56Sopenharmony_ci            PyErr_Clear();
11957db96d56Sopenharmony_ci            return DKIX_EMPTY;
11967db96d56Sopenharmony_ci        }
11977db96d56Sopenharmony_ci    }
11987db96d56Sopenharmony_ci    Py_ssize_t ix = unicodekeys_lookup_unicode(keys, name, hash);
11997db96d56Sopenharmony_ci    if (ix == DKIX_EMPTY) {
12007db96d56Sopenharmony_ci        if (keys->dk_usable <= 0) {
12017db96d56Sopenharmony_ci            return DKIX_EMPTY;
12027db96d56Sopenharmony_ci        }
12037db96d56Sopenharmony_ci        Py_INCREF(name);
12047db96d56Sopenharmony_ci        /* Insert into new slot. */
12057db96d56Sopenharmony_ci        keys->dk_version = 0;
12067db96d56Sopenharmony_ci        Py_ssize_t hashpos = find_empty_slot(keys, hash);
12077db96d56Sopenharmony_ci        ix = keys->dk_nentries;
12087db96d56Sopenharmony_ci        PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(keys)[ix];
12097db96d56Sopenharmony_ci        dictkeys_set_index(keys, hashpos, ix);
12107db96d56Sopenharmony_ci        assert(ep->me_key == NULL);
12117db96d56Sopenharmony_ci        ep->me_key = name;
12127db96d56Sopenharmony_ci        keys->dk_usable--;
12137db96d56Sopenharmony_ci        keys->dk_nentries++;
12147db96d56Sopenharmony_ci    }
12157db96d56Sopenharmony_ci    assert (ix < SHARED_KEYS_MAX_SIZE);
12167db96d56Sopenharmony_ci    return ix;
12177db96d56Sopenharmony_ci}
12187db96d56Sopenharmony_ci
12197db96d56Sopenharmony_ci/*
12207db96d56Sopenharmony_ciInternal routine to insert a new item into the table.
12217db96d56Sopenharmony_ciUsed both by the internal resize routine and by the public insert routine.
12227db96d56Sopenharmony_ciReturns -1 if an error occurred, or 0 on success.
12237db96d56Sopenharmony_ciConsumes key and value references.
12247db96d56Sopenharmony_ci*/
12257db96d56Sopenharmony_cistatic int
12267db96d56Sopenharmony_ciinsertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
12277db96d56Sopenharmony_ci{
12287db96d56Sopenharmony_ci    PyObject *old_value;
12297db96d56Sopenharmony_ci
12307db96d56Sopenharmony_ci    if (DK_IS_UNICODE(mp->ma_keys) && !PyUnicode_CheckExact(key)) {
12317db96d56Sopenharmony_ci        if (insertion_resize(mp, 0) < 0)
12327db96d56Sopenharmony_ci            goto Fail;
12337db96d56Sopenharmony_ci        assert(mp->ma_keys->dk_kind == DICT_KEYS_GENERAL);
12347db96d56Sopenharmony_ci    }
12357db96d56Sopenharmony_ci
12367db96d56Sopenharmony_ci    Py_ssize_t ix = _Py_dict_lookup(mp, key, hash, &old_value);
12377db96d56Sopenharmony_ci    if (ix == DKIX_ERROR)
12387db96d56Sopenharmony_ci        goto Fail;
12397db96d56Sopenharmony_ci
12407db96d56Sopenharmony_ci    MAINTAIN_TRACKING(mp, key, value);
12417db96d56Sopenharmony_ci
12427db96d56Sopenharmony_ci    if (ix == DKIX_EMPTY) {
12437db96d56Sopenharmony_ci        /* Insert into new slot. */
12447db96d56Sopenharmony_ci        mp->ma_keys->dk_version = 0;
12457db96d56Sopenharmony_ci        assert(old_value == NULL);
12467db96d56Sopenharmony_ci        if (mp->ma_keys->dk_usable <= 0) {
12477db96d56Sopenharmony_ci            /* Need to resize. */
12487db96d56Sopenharmony_ci            if (insertion_resize(mp, 1) < 0)
12497db96d56Sopenharmony_ci                goto Fail;
12507db96d56Sopenharmony_ci        }
12517db96d56Sopenharmony_ci
12527db96d56Sopenharmony_ci        Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash);
12537db96d56Sopenharmony_ci        dictkeys_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
12547db96d56Sopenharmony_ci
12557db96d56Sopenharmony_ci        if (DK_IS_UNICODE(mp->ma_keys)) {
12567db96d56Sopenharmony_ci            PyDictUnicodeEntry *ep;
12577db96d56Sopenharmony_ci            ep = &DK_UNICODE_ENTRIES(mp->ma_keys)[mp->ma_keys->dk_nentries];
12587db96d56Sopenharmony_ci            ep->me_key = key;
12597db96d56Sopenharmony_ci            if (mp->ma_values) {
12607db96d56Sopenharmony_ci                Py_ssize_t index = mp->ma_keys->dk_nentries;
12617db96d56Sopenharmony_ci                _PyDictValues_AddToInsertionOrder(mp->ma_values, index);
12627db96d56Sopenharmony_ci                assert (mp->ma_values->values[index] == NULL);
12637db96d56Sopenharmony_ci                mp->ma_values->values[index] = value;
12647db96d56Sopenharmony_ci            }
12657db96d56Sopenharmony_ci            else {
12667db96d56Sopenharmony_ci                ep->me_value = value;
12677db96d56Sopenharmony_ci            }
12687db96d56Sopenharmony_ci        }
12697db96d56Sopenharmony_ci        else {
12707db96d56Sopenharmony_ci            PyDictKeyEntry *ep;
12717db96d56Sopenharmony_ci            ep = &DK_ENTRIES(mp->ma_keys)[mp->ma_keys->dk_nentries];
12727db96d56Sopenharmony_ci            ep->me_key = key;
12737db96d56Sopenharmony_ci            ep->me_hash = hash;
12747db96d56Sopenharmony_ci            ep->me_value = value;
12757db96d56Sopenharmony_ci        }
12767db96d56Sopenharmony_ci        mp->ma_used++;
12777db96d56Sopenharmony_ci        mp->ma_version_tag = DICT_NEXT_VERSION();
12787db96d56Sopenharmony_ci        mp->ma_keys->dk_usable--;
12797db96d56Sopenharmony_ci        mp->ma_keys->dk_nentries++;
12807db96d56Sopenharmony_ci        assert(mp->ma_keys->dk_usable >= 0);
12817db96d56Sopenharmony_ci        ASSERT_CONSISTENT(mp);
12827db96d56Sopenharmony_ci        return 0;
12837db96d56Sopenharmony_ci    }
12847db96d56Sopenharmony_ci
12857db96d56Sopenharmony_ci    if (old_value != value) {
12867db96d56Sopenharmony_ci        if (_PyDict_HasSplitTable(mp)) {
12877db96d56Sopenharmony_ci            mp->ma_values->values[ix] = value;
12887db96d56Sopenharmony_ci            if (old_value == NULL) {
12897db96d56Sopenharmony_ci                _PyDictValues_AddToInsertionOrder(mp->ma_values, ix);
12907db96d56Sopenharmony_ci                mp->ma_used++;
12917db96d56Sopenharmony_ci            }
12927db96d56Sopenharmony_ci        }
12937db96d56Sopenharmony_ci        else {
12947db96d56Sopenharmony_ci            assert(old_value != NULL);
12957db96d56Sopenharmony_ci            if (DK_IS_UNICODE(mp->ma_keys)) {
12967db96d56Sopenharmony_ci                DK_UNICODE_ENTRIES(mp->ma_keys)[ix].me_value = value;
12977db96d56Sopenharmony_ci            }
12987db96d56Sopenharmony_ci            else {
12997db96d56Sopenharmony_ci                DK_ENTRIES(mp->ma_keys)[ix].me_value = value;
13007db96d56Sopenharmony_ci            }
13017db96d56Sopenharmony_ci        }
13027db96d56Sopenharmony_ci        mp->ma_version_tag = DICT_NEXT_VERSION();
13037db96d56Sopenharmony_ci    }
13047db96d56Sopenharmony_ci    Py_XDECREF(old_value); /* which **CAN** re-enter (see issue #22653) */
13057db96d56Sopenharmony_ci    ASSERT_CONSISTENT(mp);
13067db96d56Sopenharmony_ci    Py_DECREF(key);
13077db96d56Sopenharmony_ci    return 0;
13087db96d56Sopenharmony_ci
13097db96d56Sopenharmony_ciFail:
13107db96d56Sopenharmony_ci    Py_DECREF(value);
13117db96d56Sopenharmony_ci    Py_DECREF(key);
13127db96d56Sopenharmony_ci    return -1;
13137db96d56Sopenharmony_ci}
13147db96d56Sopenharmony_ci
13157db96d56Sopenharmony_ci// Same to insertdict but specialized for ma_keys = Py_EMPTY_KEYS.
13167db96d56Sopenharmony_ci// Consumes key and value references.
13177db96d56Sopenharmony_cistatic int
13187db96d56Sopenharmony_ciinsert_to_emptydict(PyDictObject *mp, PyObject *key, Py_hash_t hash,
13197db96d56Sopenharmony_ci                    PyObject *value)
13207db96d56Sopenharmony_ci{
13217db96d56Sopenharmony_ci    assert(mp->ma_keys == Py_EMPTY_KEYS);
13227db96d56Sopenharmony_ci
13237db96d56Sopenharmony_ci    int unicode = PyUnicode_CheckExact(key);
13247db96d56Sopenharmony_ci    PyDictKeysObject *newkeys = new_keys_object(PyDict_LOG_MINSIZE, unicode);
13257db96d56Sopenharmony_ci    if (newkeys == NULL) {
13267db96d56Sopenharmony_ci        Py_DECREF(key);
13277db96d56Sopenharmony_ci        Py_DECREF(value);
13287db96d56Sopenharmony_ci        return -1;
13297db96d56Sopenharmony_ci    }
13307db96d56Sopenharmony_ci    dictkeys_decref(Py_EMPTY_KEYS);
13317db96d56Sopenharmony_ci    mp->ma_keys = newkeys;
13327db96d56Sopenharmony_ci    mp->ma_values = NULL;
13337db96d56Sopenharmony_ci
13347db96d56Sopenharmony_ci    MAINTAIN_TRACKING(mp, key, value);
13357db96d56Sopenharmony_ci
13367db96d56Sopenharmony_ci    size_t hashpos = (size_t)hash & (PyDict_MINSIZE-1);
13377db96d56Sopenharmony_ci    dictkeys_set_index(mp->ma_keys, hashpos, 0);
13387db96d56Sopenharmony_ci    if (unicode) {
13397db96d56Sopenharmony_ci        PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(mp->ma_keys);
13407db96d56Sopenharmony_ci        ep->me_key = key;
13417db96d56Sopenharmony_ci        ep->me_value = value;
13427db96d56Sopenharmony_ci    }
13437db96d56Sopenharmony_ci    else {
13447db96d56Sopenharmony_ci        PyDictKeyEntry *ep = DK_ENTRIES(mp->ma_keys);
13457db96d56Sopenharmony_ci        ep->me_key = key;
13467db96d56Sopenharmony_ci        ep->me_hash = hash;
13477db96d56Sopenharmony_ci        ep->me_value = value;
13487db96d56Sopenharmony_ci    }
13497db96d56Sopenharmony_ci    mp->ma_used++;
13507db96d56Sopenharmony_ci    mp->ma_version_tag = DICT_NEXT_VERSION();
13517db96d56Sopenharmony_ci    mp->ma_keys->dk_usable--;
13527db96d56Sopenharmony_ci    mp->ma_keys->dk_nentries++;
13537db96d56Sopenharmony_ci    return 0;
13547db96d56Sopenharmony_ci}
13557db96d56Sopenharmony_ci
13567db96d56Sopenharmony_ci/*
13577db96d56Sopenharmony_ciInternal routine used by dictresize() to build a hashtable of entries.
13587db96d56Sopenharmony_ci*/
13597db96d56Sopenharmony_cistatic void
13607db96d56Sopenharmony_cibuild_indices_generic(PyDictKeysObject *keys, PyDictKeyEntry *ep, Py_ssize_t n)
13617db96d56Sopenharmony_ci{
13627db96d56Sopenharmony_ci    size_t mask = DK_MASK(keys);
13637db96d56Sopenharmony_ci    for (Py_ssize_t ix = 0; ix != n; ix++, ep++) {
13647db96d56Sopenharmony_ci        Py_hash_t hash = ep->me_hash;
13657db96d56Sopenharmony_ci        size_t i = hash & mask;
13667db96d56Sopenharmony_ci        for (size_t perturb = hash; dictkeys_get_index(keys, i) != DKIX_EMPTY;) {
13677db96d56Sopenharmony_ci            perturb >>= PERTURB_SHIFT;
13687db96d56Sopenharmony_ci            i = mask & (i*5 + perturb + 1);
13697db96d56Sopenharmony_ci        }
13707db96d56Sopenharmony_ci        dictkeys_set_index(keys, i, ix);
13717db96d56Sopenharmony_ci    }
13727db96d56Sopenharmony_ci}
13737db96d56Sopenharmony_ci
13747db96d56Sopenharmony_cistatic void
13757db96d56Sopenharmony_cibuild_indices_unicode(PyDictKeysObject *keys, PyDictUnicodeEntry *ep, Py_ssize_t n)
13767db96d56Sopenharmony_ci{
13777db96d56Sopenharmony_ci    size_t mask = DK_MASK(keys);
13787db96d56Sopenharmony_ci    for (Py_ssize_t ix = 0; ix != n; ix++, ep++) {
13797db96d56Sopenharmony_ci        Py_hash_t hash = unicode_get_hash(ep->me_key);
13807db96d56Sopenharmony_ci        assert(hash != -1);
13817db96d56Sopenharmony_ci        size_t i = hash & mask;
13827db96d56Sopenharmony_ci        for (size_t perturb = hash; dictkeys_get_index(keys, i) != DKIX_EMPTY;) {
13837db96d56Sopenharmony_ci            perturb >>= PERTURB_SHIFT;
13847db96d56Sopenharmony_ci            i = mask & (i*5 + perturb + 1);
13857db96d56Sopenharmony_ci        }
13867db96d56Sopenharmony_ci        dictkeys_set_index(keys, i, ix);
13877db96d56Sopenharmony_ci    }
13887db96d56Sopenharmony_ci}
13897db96d56Sopenharmony_ci
13907db96d56Sopenharmony_ci/*
13917db96d56Sopenharmony_ciRestructure the table by allocating a new table and reinserting all
13927db96d56Sopenharmony_ciitems again.  When entries have been deleted, the new table may
13937db96d56Sopenharmony_ciactually be smaller than the old one.
13947db96d56Sopenharmony_ciIf a table is split (its keys and hashes are shared, its values are not),
13957db96d56Sopenharmony_cithen the values are temporarily copied into the table, it is resized as
13967db96d56Sopenharmony_cia combined table, then the me_value slots in the old table are NULLed out.
13977db96d56Sopenharmony_ciAfter resizing a table is always combined.
13987db96d56Sopenharmony_ci
13997db96d56Sopenharmony_ciThis function supports:
14007db96d56Sopenharmony_ci - Unicode split -> Unicode combined or Generic
14017db96d56Sopenharmony_ci - Unicode combined -> Unicode combined or Generic
14027db96d56Sopenharmony_ci - Generic -> Generic
14037db96d56Sopenharmony_ci*/
14047db96d56Sopenharmony_cistatic int
14057db96d56Sopenharmony_cidictresize(PyDictObject *mp, uint8_t log2_newsize, int unicode)
14067db96d56Sopenharmony_ci{
14077db96d56Sopenharmony_ci    PyDictKeysObject *oldkeys;
14087db96d56Sopenharmony_ci    PyDictValues *oldvalues;
14097db96d56Sopenharmony_ci
14107db96d56Sopenharmony_ci    if (log2_newsize >= SIZEOF_SIZE_T*8) {
14117db96d56Sopenharmony_ci        PyErr_NoMemory();
14127db96d56Sopenharmony_ci        return -1;
14137db96d56Sopenharmony_ci    }
14147db96d56Sopenharmony_ci    assert(log2_newsize >= PyDict_LOG_MINSIZE);
14157db96d56Sopenharmony_ci
14167db96d56Sopenharmony_ci    oldkeys = mp->ma_keys;
14177db96d56Sopenharmony_ci    oldvalues = mp->ma_values;
14187db96d56Sopenharmony_ci
14197db96d56Sopenharmony_ci    if (!DK_IS_UNICODE(oldkeys)) {
14207db96d56Sopenharmony_ci        unicode = 0;
14217db96d56Sopenharmony_ci    }
14227db96d56Sopenharmony_ci
14237db96d56Sopenharmony_ci    /* NOTE: Current odict checks mp->ma_keys to detect resize happen.
14247db96d56Sopenharmony_ci     * So we can't reuse oldkeys even if oldkeys->dk_size == newsize.
14257db96d56Sopenharmony_ci     * TODO: Try reusing oldkeys when reimplement odict.
14267db96d56Sopenharmony_ci     */
14277db96d56Sopenharmony_ci
14287db96d56Sopenharmony_ci    /* Allocate a new table. */
14297db96d56Sopenharmony_ci    mp->ma_keys = new_keys_object(log2_newsize, unicode);
14307db96d56Sopenharmony_ci    if (mp->ma_keys == NULL) {
14317db96d56Sopenharmony_ci        mp->ma_keys = oldkeys;
14327db96d56Sopenharmony_ci        return -1;
14337db96d56Sopenharmony_ci    }
14347db96d56Sopenharmony_ci    // New table must be large enough.
14357db96d56Sopenharmony_ci    assert(mp->ma_keys->dk_usable >= mp->ma_used);
14367db96d56Sopenharmony_ci
14377db96d56Sopenharmony_ci    Py_ssize_t numentries = mp->ma_used;
14387db96d56Sopenharmony_ci
14397db96d56Sopenharmony_ci    if (oldvalues != NULL) {
14407db96d56Sopenharmony_ci         PyDictUnicodeEntry *oldentries = DK_UNICODE_ENTRIES(oldkeys);
14417db96d56Sopenharmony_ci        /* Convert split table into new combined table.
14427db96d56Sopenharmony_ci         * We must incref keys; we can transfer values.
14437db96d56Sopenharmony_ci         */
14447db96d56Sopenharmony_ci        if (mp->ma_keys->dk_kind == DICT_KEYS_GENERAL) {
14457db96d56Sopenharmony_ci            // split -> generic
14467db96d56Sopenharmony_ci            PyDictKeyEntry *newentries = DK_ENTRIES(mp->ma_keys);
14477db96d56Sopenharmony_ci
14487db96d56Sopenharmony_ci            for (Py_ssize_t i = 0; i < numentries; i++) {
14497db96d56Sopenharmony_ci                int index = get_index_from_order(mp, i);
14507db96d56Sopenharmony_ci                PyDictUnicodeEntry *ep = &oldentries[index];
14517db96d56Sopenharmony_ci                assert(oldvalues->values[index] != NULL);
14527db96d56Sopenharmony_ci                Py_INCREF(ep->me_key);
14537db96d56Sopenharmony_ci                newentries[i].me_key = ep->me_key;
14547db96d56Sopenharmony_ci                newentries[i].me_hash = unicode_get_hash(ep->me_key);
14557db96d56Sopenharmony_ci                newentries[i].me_value = oldvalues->values[index];
14567db96d56Sopenharmony_ci            }
14577db96d56Sopenharmony_ci            build_indices_generic(mp->ma_keys, newentries, numentries);
14587db96d56Sopenharmony_ci        }
14597db96d56Sopenharmony_ci        else { // split -> combined unicode
14607db96d56Sopenharmony_ci            PyDictUnicodeEntry *newentries = DK_UNICODE_ENTRIES(mp->ma_keys);
14617db96d56Sopenharmony_ci
14627db96d56Sopenharmony_ci            for (Py_ssize_t i = 0; i < numentries; i++) {
14637db96d56Sopenharmony_ci                int index = get_index_from_order(mp, i);
14647db96d56Sopenharmony_ci                PyDictUnicodeEntry *ep = &oldentries[index];
14657db96d56Sopenharmony_ci                assert(oldvalues->values[index] != NULL);
14667db96d56Sopenharmony_ci                Py_INCREF(ep->me_key);
14677db96d56Sopenharmony_ci                newentries[i].me_key = ep->me_key;
14687db96d56Sopenharmony_ci                newentries[i].me_value = oldvalues->values[index];
14697db96d56Sopenharmony_ci            }
14707db96d56Sopenharmony_ci            build_indices_unicode(mp->ma_keys, newentries, numentries);
14717db96d56Sopenharmony_ci        }
14727db96d56Sopenharmony_ci        dictkeys_decref(oldkeys);
14737db96d56Sopenharmony_ci        mp->ma_values = NULL;
14747db96d56Sopenharmony_ci        free_values(oldvalues);
14757db96d56Sopenharmony_ci    }
14767db96d56Sopenharmony_ci    else {  // oldkeys is combined.
14777db96d56Sopenharmony_ci        if (oldkeys->dk_kind == DICT_KEYS_GENERAL) {
14787db96d56Sopenharmony_ci            // generic -> generic
14797db96d56Sopenharmony_ci            assert(mp->ma_keys->dk_kind == DICT_KEYS_GENERAL);
14807db96d56Sopenharmony_ci            PyDictKeyEntry *oldentries = DK_ENTRIES(oldkeys);
14817db96d56Sopenharmony_ci            PyDictKeyEntry *newentries = DK_ENTRIES(mp->ma_keys);
14827db96d56Sopenharmony_ci            if (oldkeys->dk_nentries == numentries) {
14837db96d56Sopenharmony_ci                memcpy(newentries, oldentries, numentries * sizeof(PyDictKeyEntry));
14847db96d56Sopenharmony_ci            }
14857db96d56Sopenharmony_ci            else {
14867db96d56Sopenharmony_ci                PyDictKeyEntry *ep = oldentries;
14877db96d56Sopenharmony_ci                for (Py_ssize_t i = 0; i < numentries; i++) {
14887db96d56Sopenharmony_ci                    while (ep->me_value == NULL)
14897db96d56Sopenharmony_ci                        ep++;
14907db96d56Sopenharmony_ci                    newentries[i] = *ep++;
14917db96d56Sopenharmony_ci                }
14927db96d56Sopenharmony_ci            }
14937db96d56Sopenharmony_ci            build_indices_generic(mp->ma_keys, newentries, numentries);
14947db96d56Sopenharmony_ci        }
14957db96d56Sopenharmony_ci        else {  // oldkeys is combined unicode
14967db96d56Sopenharmony_ci            PyDictUnicodeEntry *oldentries = DK_UNICODE_ENTRIES(oldkeys);
14977db96d56Sopenharmony_ci            if (unicode) { // combined unicode -> combined unicode
14987db96d56Sopenharmony_ci                PyDictUnicodeEntry *newentries = DK_UNICODE_ENTRIES(mp->ma_keys);
14997db96d56Sopenharmony_ci                if (oldkeys->dk_nentries == numentries && mp->ma_keys->dk_kind == DICT_KEYS_UNICODE) {
15007db96d56Sopenharmony_ci                    memcpy(newentries, oldentries, numentries * sizeof(PyDictUnicodeEntry));
15017db96d56Sopenharmony_ci                }
15027db96d56Sopenharmony_ci                else {
15037db96d56Sopenharmony_ci                    PyDictUnicodeEntry *ep = oldentries;
15047db96d56Sopenharmony_ci                    for (Py_ssize_t i = 0; i < numentries; i++) {
15057db96d56Sopenharmony_ci                        while (ep->me_value == NULL)
15067db96d56Sopenharmony_ci                            ep++;
15077db96d56Sopenharmony_ci                        newentries[i] = *ep++;
15087db96d56Sopenharmony_ci                    }
15097db96d56Sopenharmony_ci                }
15107db96d56Sopenharmony_ci                build_indices_unicode(mp->ma_keys, newentries, numentries);
15117db96d56Sopenharmony_ci            }
15127db96d56Sopenharmony_ci            else { // combined unicode -> generic
15137db96d56Sopenharmony_ci                PyDictKeyEntry *newentries = DK_ENTRIES(mp->ma_keys);
15147db96d56Sopenharmony_ci                PyDictUnicodeEntry *ep = oldentries;
15157db96d56Sopenharmony_ci                for (Py_ssize_t i = 0; i < numentries; i++) {
15167db96d56Sopenharmony_ci                    while (ep->me_value == NULL)
15177db96d56Sopenharmony_ci                        ep++;
15187db96d56Sopenharmony_ci                    newentries[i].me_key = ep->me_key;
15197db96d56Sopenharmony_ci                    newentries[i].me_hash = unicode_get_hash(ep->me_key);
15207db96d56Sopenharmony_ci                    newentries[i].me_value = ep->me_value;
15217db96d56Sopenharmony_ci                    ep++;
15227db96d56Sopenharmony_ci                }
15237db96d56Sopenharmony_ci                build_indices_generic(mp->ma_keys, newentries, numentries);
15247db96d56Sopenharmony_ci            }
15257db96d56Sopenharmony_ci        }
15267db96d56Sopenharmony_ci
15277db96d56Sopenharmony_ci        // We can not use free_keys_object here because key's reference
15287db96d56Sopenharmony_ci        // are moved already.
15297db96d56Sopenharmony_ci#ifdef Py_REF_DEBUG
15307db96d56Sopenharmony_ci        _Py_RefTotal--;
15317db96d56Sopenharmony_ci#endif
15327db96d56Sopenharmony_ci        if (oldkeys == Py_EMPTY_KEYS) {
15337db96d56Sopenharmony_ci            oldkeys->dk_refcnt--;
15347db96d56Sopenharmony_ci            assert(oldkeys->dk_refcnt > 0);
15357db96d56Sopenharmony_ci        }
15367db96d56Sopenharmony_ci        else {
15377db96d56Sopenharmony_ci            assert(oldkeys->dk_kind != DICT_KEYS_SPLIT);
15387db96d56Sopenharmony_ci            assert(oldkeys->dk_refcnt == 1);
15397db96d56Sopenharmony_ci#if PyDict_MAXFREELIST > 0
15407db96d56Sopenharmony_ci            struct _Py_dict_state *state = get_dict_state();
15417db96d56Sopenharmony_ci#ifdef Py_DEBUG
15427db96d56Sopenharmony_ci            // dictresize() must not be called after _PyDict_Fini()
15437db96d56Sopenharmony_ci            assert(state->keys_numfree != -1);
15447db96d56Sopenharmony_ci#endif
15457db96d56Sopenharmony_ci            if (DK_LOG_SIZE(oldkeys) == PyDict_LOG_MINSIZE &&
15467db96d56Sopenharmony_ci                    DK_IS_UNICODE(oldkeys) &&
15477db96d56Sopenharmony_ci                    state->keys_numfree < PyDict_MAXFREELIST)
15487db96d56Sopenharmony_ci            {
15497db96d56Sopenharmony_ci                state->keys_free_list[state->keys_numfree++] = oldkeys;
15507db96d56Sopenharmony_ci                OBJECT_STAT_INC(to_freelist);
15517db96d56Sopenharmony_ci            }
15527db96d56Sopenharmony_ci            else
15537db96d56Sopenharmony_ci#endif
15547db96d56Sopenharmony_ci            {
15557db96d56Sopenharmony_ci                PyObject_Free(oldkeys);
15567db96d56Sopenharmony_ci            }
15577db96d56Sopenharmony_ci        }
15587db96d56Sopenharmony_ci    }
15597db96d56Sopenharmony_ci
15607db96d56Sopenharmony_ci    mp->ma_keys->dk_usable -= numentries;
15617db96d56Sopenharmony_ci    mp->ma_keys->dk_nentries = numentries;
15627db96d56Sopenharmony_ci    ASSERT_CONSISTENT(mp);
15637db96d56Sopenharmony_ci    return 0;
15647db96d56Sopenharmony_ci}
15657db96d56Sopenharmony_ci
15667db96d56Sopenharmony_cistatic PyObject *
15677db96d56Sopenharmony_cidict_new_presized(Py_ssize_t minused, bool unicode)
15687db96d56Sopenharmony_ci{
15697db96d56Sopenharmony_ci    const uint8_t log2_max_presize = 17;
15707db96d56Sopenharmony_ci    const Py_ssize_t max_presize = ((Py_ssize_t)1) << log2_max_presize;
15717db96d56Sopenharmony_ci    uint8_t log2_newsize;
15727db96d56Sopenharmony_ci    PyDictKeysObject *new_keys;
15737db96d56Sopenharmony_ci
15747db96d56Sopenharmony_ci    if (minused <= USABLE_FRACTION(PyDict_MINSIZE)) {
15757db96d56Sopenharmony_ci        return PyDict_New();
15767db96d56Sopenharmony_ci    }
15777db96d56Sopenharmony_ci    /* There are no strict guarantee that returned dict can contain minused
15787db96d56Sopenharmony_ci     * items without resize.  So we create medium size dict instead of very
15797db96d56Sopenharmony_ci     * large dict or MemoryError.
15807db96d56Sopenharmony_ci     */
15817db96d56Sopenharmony_ci    if (minused > USABLE_FRACTION(max_presize)) {
15827db96d56Sopenharmony_ci        log2_newsize = log2_max_presize;
15837db96d56Sopenharmony_ci    }
15847db96d56Sopenharmony_ci    else {
15857db96d56Sopenharmony_ci        log2_newsize = estimate_log2_keysize(minused);
15867db96d56Sopenharmony_ci    }
15877db96d56Sopenharmony_ci
15887db96d56Sopenharmony_ci    new_keys = new_keys_object(log2_newsize, unicode);
15897db96d56Sopenharmony_ci    if (new_keys == NULL)
15907db96d56Sopenharmony_ci        return NULL;
15917db96d56Sopenharmony_ci    return new_dict(new_keys, NULL, 0, 0);
15927db96d56Sopenharmony_ci}
15937db96d56Sopenharmony_ci
15947db96d56Sopenharmony_ciPyObject *
15957db96d56Sopenharmony_ci_PyDict_NewPresized(Py_ssize_t minused)
15967db96d56Sopenharmony_ci{
15977db96d56Sopenharmony_ci    return dict_new_presized(minused, false);
15987db96d56Sopenharmony_ci}
15997db96d56Sopenharmony_ci
16007db96d56Sopenharmony_ciPyObject *
16017db96d56Sopenharmony_ci_PyDict_FromItems(PyObject *const *keys, Py_ssize_t keys_offset,
16027db96d56Sopenharmony_ci                  PyObject *const *values, Py_ssize_t values_offset,
16037db96d56Sopenharmony_ci                  Py_ssize_t length)
16047db96d56Sopenharmony_ci{
16057db96d56Sopenharmony_ci    bool unicode = true;
16067db96d56Sopenharmony_ci    PyObject *const *ks = keys;
16077db96d56Sopenharmony_ci
16087db96d56Sopenharmony_ci    for (Py_ssize_t i = 0; i < length; i++) {
16097db96d56Sopenharmony_ci        if (!PyUnicode_CheckExact(*ks)) {
16107db96d56Sopenharmony_ci            unicode = false;
16117db96d56Sopenharmony_ci            break;
16127db96d56Sopenharmony_ci        }
16137db96d56Sopenharmony_ci        ks += keys_offset;
16147db96d56Sopenharmony_ci    }
16157db96d56Sopenharmony_ci
16167db96d56Sopenharmony_ci    PyObject *dict = dict_new_presized(length, unicode);
16177db96d56Sopenharmony_ci    if (dict == NULL) {
16187db96d56Sopenharmony_ci        return NULL;
16197db96d56Sopenharmony_ci    }
16207db96d56Sopenharmony_ci
16217db96d56Sopenharmony_ci    ks = keys;
16227db96d56Sopenharmony_ci    PyObject *const *vs = values;
16237db96d56Sopenharmony_ci
16247db96d56Sopenharmony_ci    for (Py_ssize_t i = 0; i < length; i++) {
16257db96d56Sopenharmony_ci        PyObject *key = *ks;
16267db96d56Sopenharmony_ci        PyObject *value = *vs;
16277db96d56Sopenharmony_ci        if (PyDict_SetItem(dict, key, value) < 0) {
16287db96d56Sopenharmony_ci            Py_DECREF(dict);
16297db96d56Sopenharmony_ci            return NULL;
16307db96d56Sopenharmony_ci        }
16317db96d56Sopenharmony_ci        ks += keys_offset;
16327db96d56Sopenharmony_ci        vs += values_offset;
16337db96d56Sopenharmony_ci    }
16347db96d56Sopenharmony_ci
16357db96d56Sopenharmony_ci    return dict;
16367db96d56Sopenharmony_ci}
16377db96d56Sopenharmony_ci
16387db96d56Sopenharmony_ci/* Note that, for historical reasons, PyDict_GetItem() suppresses all errors
16397db96d56Sopenharmony_ci * that may occur (originally dicts supported only string keys, and exceptions
16407db96d56Sopenharmony_ci * weren't possible).  So, while the original intent was that a NULL return
16417db96d56Sopenharmony_ci * meant the key wasn't present, in reality it can mean that, or that an error
16427db96d56Sopenharmony_ci * (suppressed) occurred while computing the key's hash, or that some error
16437db96d56Sopenharmony_ci * (suppressed) occurred when comparing keys in the dict's internal probe
16447db96d56Sopenharmony_ci * sequence.  A nasty example of the latter is when a Python-coded comparison
16457db96d56Sopenharmony_ci * function hits a stack-depth error, which can cause this to return NULL
16467db96d56Sopenharmony_ci * even if the key is present.
16477db96d56Sopenharmony_ci */
16487db96d56Sopenharmony_ciPyObject *
16497db96d56Sopenharmony_ciPyDict_GetItem(PyObject *op, PyObject *key)
16507db96d56Sopenharmony_ci{
16517db96d56Sopenharmony_ci    if (!PyDict_Check(op)) {
16527db96d56Sopenharmony_ci        return NULL;
16537db96d56Sopenharmony_ci    }
16547db96d56Sopenharmony_ci    PyDictObject *mp = (PyDictObject *)op;
16557db96d56Sopenharmony_ci
16567db96d56Sopenharmony_ci    Py_hash_t hash;
16577db96d56Sopenharmony_ci    if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
16587db96d56Sopenharmony_ci        hash = PyObject_Hash(key);
16597db96d56Sopenharmony_ci        if (hash == -1) {
16607db96d56Sopenharmony_ci            PyErr_Clear();
16617db96d56Sopenharmony_ci            return NULL;
16627db96d56Sopenharmony_ci        }
16637db96d56Sopenharmony_ci    }
16647db96d56Sopenharmony_ci
16657db96d56Sopenharmony_ci    PyThreadState *tstate = _PyThreadState_GET();
16667db96d56Sopenharmony_ci#ifdef Py_DEBUG
16677db96d56Sopenharmony_ci    // bpo-40839: Before Python 3.10, it was possible to call PyDict_GetItem()
16687db96d56Sopenharmony_ci    // with the GIL released.
16697db96d56Sopenharmony_ci    _Py_EnsureTstateNotNULL(tstate);
16707db96d56Sopenharmony_ci#endif
16717db96d56Sopenharmony_ci
16727db96d56Sopenharmony_ci    /* Preserve the existing exception */
16737db96d56Sopenharmony_ci    PyObject *exc_type, *exc_value, *exc_tb;
16747db96d56Sopenharmony_ci    PyObject *value;
16757db96d56Sopenharmony_ci    Py_ssize_t ix; (void)ix;
16767db96d56Sopenharmony_ci
16777db96d56Sopenharmony_ci    _PyErr_Fetch(tstate, &exc_type, &exc_value, &exc_tb);
16787db96d56Sopenharmony_ci    ix = _Py_dict_lookup(mp, key, hash, &value);
16797db96d56Sopenharmony_ci
16807db96d56Sopenharmony_ci    /* Ignore any exception raised by the lookup */
16817db96d56Sopenharmony_ci    _PyErr_Restore(tstate, exc_type, exc_value, exc_tb);
16827db96d56Sopenharmony_ci
16837db96d56Sopenharmony_ci
16847db96d56Sopenharmony_ci    assert(ix >= 0 || value == NULL);
16857db96d56Sopenharmony_ci    return value;
16867db96d56Sopenharmony_ci}
16877db96d56Sopenharmony_ci
16887db96d56Sopenharmony_ciPy_ssize_t
16897db96d56Sopenharmony_ci_PyDict_GetItemHint(PyDictObject *mp, PyObject *key,
16907db96d56Sopenharmony_ci                    Py_ssize_t hint, PyObject **value)
16917db96d56Sopenharmony_ci{
16927db96d56Sopenharmony_ci    assert(*value == NULL);
16937db96d56Sopenharmony_ci    assert(PyDict_CheckExact((PyObject*)mp));
16947db96d56Sopenharmony_ci    assert(PyUnicode_CheckExact(key));
16957db96d56Sopenharmony_ci
16967db96d56Sopenharmony_ci    if (hint >= 0 && hint < mp->ma_keys->dk_nentries) {
16977db96d56Sopenharmony_ci        PyObject *res = NULL;
16987db96d56Sopenharmony_ci
16997db96d56Sopenharmony_ci        if (DK_IS_UNICODE(mp->ma_keys)) {
17007db96d56Sopenharmony_ci            PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(mp->ma_keys) + (size_t)hint;
17017db96d56Sopenharmony_ci            if (ep->me_key == key) {
17027db96d56Sopenharmony_ci                if (mp->ma_keys->dk_kind == DICT_KEYS_SPLIT) {
17037db96d56Sopenharmony_ci                    assert(mp->ma_values != NULL);
17047db96d56Sopenharmony_ci                    res = mp->ma_values->values[(size_t)hint];
17057db96d56Sopenharmony_ci                }
17067db96d56Sopenharmony_ci                else {
17077db96d56Sopenharmony_ci                    res = ep->me_value;
17087db96d56Sopenharmony_ci                }
17097db96d56Sopenharmony_ci                if (res != NULL) {
17107db96d56Sopenharmony_ci                    *value = res;
17117db96d56Sopenharmony_ci                    return hint;
17127db96d56Sopenharmony_ci                }
17137db96d56Sopenharmony_ci            }
17147db96d56Sopenharmony_ci        }
17157db96d56Sopenharmony_ci        else {
17167db96d56Sopenharmony_ci            PyDictKeyEntry *ep = DK_ENTRIES(mp->ma_keys) + (size_t)hint;
17177db96d56Sopenharmony_ci            if (ep->me_key == key) {
17187db96d56Sopenharmony_ci                if (mp->ma_keys->dk_kind == DICT_KEYS_SPLIT) {
17197db96d56Sopenharmony_ci                    assert(mp->ma_values != NULL);
17207db96d56Sopenharmony_ci                    res = mp->ma_values->values[(size_t)hint];
17217db96d56Sopenharmony_ci                }
17227db96d56Sopenharmony_ci                else {
17237db96d56Sopenharmony_ci                    res = ep->me_value;
17247db96d56Sopenharmony_ci                }
17257db96d56Sopenharmony_ci                if (res != NULL) {
17267db96d56Sopenharmony_ci                    *value = res;
17277db96d56Sopenharmony_ci                    return hint;
17287db96d56Sopenharmony_ci                }
17297db96d56Sopenharmony_ci            }
17307db96d56Sopenharmony_ci        }
17317db96d56Sopenharmony_ci    }
17327db96d56Sopenharmony_ci
17337db96d56Sopenharmony_ci    Py_hash_t hash = unicode_get_hash(key);
17347db96d56Sopenharmony_ci    if (hash == -1) {
17357db96d56Sopenharmony_ci        hash = PyObject_Hash(key);
17367db96d56Sopenharmony_ci        if (hash == -1) {
17377db96d56Sopenharmony_ci            return -1;
17387db96d56Sopenharmony_ci        }
17397db96d56Sopenharmony_ci    }
17407db96d56Sopenharmony_ci
17417db96d56Sopenharmony_ci    return _Py_dict_lookup(mp, key, hash, value);
17427db96d56Sopenharmony_ci}
17437db96d56Sopenharmony_ci
17447db96d56Sopenharmony_ci/* Same as PyDict_GetItemWithError() but with hash supplied by caller.
17457db96d56Sopenharmony_ci   This returns NULL *with* an exception set if an exception occurred.
17467db96d56Sopenharmony_ci   It returns NULL *without* an exception set if the key wasn't present.
17477db96d56Sopenharmony_ci*/
17487db96d56Sopenharmony_ciPyObject *
17497db96d56Sopenharmony_ci_PyDict_GetItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
17507db96d56Sopenharmony_ci{
17517db96d56Sopenharmony_ci    Py_ssize_t ix; (void)ix;
17527db96d56Sopenharmony_ci    PyDictObject *mp = (PyDictObject *)op;
17537db96d56Sopenharmony_ci    PyObject *value;
17547db96d56Sopenharmony_ci
17557db96d56Sopenharmony_ci    if (!PyDict_Check(op)) {
17567db96d56Sopenharmony_ci        PyErr_BadInternalCall();
17577db96d56Sopenharmony_ci        return NULL;
17587db96d56Sopenharmony_ci    }
17597db96d56Sopenharmony_ci
17607db96d56Sopenharmony_ci    ix = _Py_dict_lookup(mp, key, hash, &value);
17617db96d56Sopenharmony_ci    assert(ix >= 0 || value == NULL);
17627db96d56Sopenharmony_ci    return value;
17637db96d56Sopenharmony_ci}
17647db96d56Sopenharmony_ci
17657db96d56Sopenharmony_ci/* Variant of PyDict_GetItem() that doesn't suppress exceptions.
17667db96d56Sopenharmony_ci   This returns NULL *with* an exception set if an exception occurred.
17677db96d56Sopenharmony_ci   It returns NULL *without* an exception set if the key wasn't present.
17687db96d56Sopenharmony_ci*/
17697db96d56Sopenharmony_ciPyObject *
17707db96d56Sopenharmony_ciPyDict_GetItemWithError(PyObject *op, PyObject *key)
17717db96d56Sopenharmony_ci{
17727db96d56Sopenharmony_ci    Py_ssize_t ix; (void)ix;
17737db96d56Sopenharmony_ci    Py_hash_t hash;
17747db96d56Sopenharmony_ci    PyDictObject*mp = (PyDictObject *)op;
17757db96d56Sopenharmony_ci    PyObject *value;
17767db96d56Sopenharmony_ci
17777db96d56Sopenharmony_ci    if (!PyDict_Check(op)) {
17787db96d56Sopenharmony_ci        PyErr_BadInternalCall();
17797db96d56Sopenharmony_ci        return NULL;
17807db96d56Sopenharmony_ci    }
17817db96d56Sopenharmony_ci    if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1)
17827db96d56Sopenharmony_ci    {
17837db96d56Sopenharmony_ci        hash = PyObject_Hash(key);
17847db96d56Sopenharmony_ci        if (hash == -1) {
17857db96d56Sopenharmony_ci            return NULL;
17867db96d56Sopenharmony_ci        }
17877db96d56Sopenharmony_ci    }
17887db96d56Sopenharmony_ci
17897db96d56Sopenharmony_ci    ix = _Py_dict_lookup(mp, key, hash, &value);
17907db96d56Sopenharmony_ci    assert(ix >= 0 || value == NULL);
17917db96d56Sopenharmony_ci    return value;
17927db96d56Sopenharmony_ci}
17937db96d56Sopenharmony_ci
17947db96d56Sopenharmony_ciPyObject *
17957db96d56Sopenharmony_ci_PyDict_GetItemWithError(PyObject *dp, PyObject *kv)
17967db96d56Sopenharmony_ci{
17977db96d56Sopenharmony_ci    assert(PyUnicode_CheckExact(kv));
17987db96d56Sopenharmony_ci    Py_hash_t hash = kv->ob_type->tp_hash(kv);
17997db96d56Sopenharmony_ci    if (hash == -1) {
18007db96d56Sopenharmony_ci        return NULL;
18017db96d56Sopenharmony_ci    }
18027db96d56Sopenharmony_ci    return _PyDict_GetItem_KnownHash(dp, kv, hash);
18037db96d56Sopenharmony_ci}
18047db96d56Sopenharmony_ci
18057db96d56Sopenharmony_ciPyObject *
18067db96d56Sopenharmony_ci_PyDict_GetItemIdWithError(PyObject *dp, _Py_Identifier *key)
18077db96d56Sopenharmony_ci{
18087db96d56Sopenharmony_ci    PyObject *kv;
18097db96d56Sopenharmony_ci    kv = _PyUnicode_FromId(key); /* borrowed */
18107db96d56Sopenharmony_ci    if (kv == NULL)
18117db96d56Sopenharmony_ci        return NULL;
18127db96d56Sopenharmony_ci    Py_hash_t hash = unicode_get_hash(kv);
18137db96d56Sopenharmony_ci    assert (hash != -1);  /* interned strings have their hash value initialised */
18147db96d56Sopenharmony_ci    return _PyDict_GetItem_KnownHash(dp, kv, hash);
18157db96d56Sopenharmony_ci}
18167db96d56Sopenharmony_ci
18177db96d56Sopenharmony_ciPyObject *
18187db96d56Sopenharmony_ci_PyDict_GetItemStringWithError(PyObject *v, const char *key)
18197db96d56Sopenharmony_ci{
18207db96d56Sopenharmony_ci    PyObject *kv, *rv;
18217db96d56Sopenharmony_ci    kv = PyUnicode_FromString(key);
18227db96d56Sopenharmony_ci    if (kv == NULL) {
18237db96d56Sopenharmony_ci        return NULL;
18247db96d56Sopenharmony_ci    }
18257db96d56Sopenharmony_ci    rv = PyDict_GetItemWithError(v, kv);
18267db96d56Sopenharmony_ci    Py_DECREF(kv);
18277db96d56Sopenharmony_ci    return rv;
18287db96d56Sopenharmony_ci}
18297db96d56Sopenharmony_ci
18307db96d56Sopenharmony_ci/* Fast version of global value lookup (LOAD_GLOBAL).
18317db96d56Sopenharmony_ci * Lookup in globals, then builtins.
18327db96d56Sopenharmony_ci *
18337db96d56Sopenharmony_ci *
18347db96d56Sopenharmony_ci *
18357db96d56Sopenharmony_ci *
18367db96d56Sopenharmony_ci * Raise an exception and return NULL if an error occurred (ex: computing the
18377db96d56Sopenharmony_ci * key hash failed, key comparison failed, ...). Return NULL if the key doesn't
18387db96d56Sopenharmony_ci * exist. Return the value if the key exists.
18397db96d56Sopenharmony_ci */
18407db96d56Sopenharmony_ciPyObject *
18417db96d56Sopenharmony_ci_PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key)
18427db96d56Sopenharmony_ci{
18437db96d56Sopenharmony_ci    Py_ssize_t ix;
18447db96d56Sopenharmony_ci    Py_hash_t hash;
18457db96d56Sopenharmony_ci    PyObject *value;
18467db96d56Sopenharmony_ci
18477db96d56Sopenharmony_ci    if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
18487db96d56Sopenharmony_ci        hash = PyObject_Hash(key);
18497db96d56Sopenharmony_ci        if (hash == -1)
18507db96d56Sopenharmony_ci            return NULL;
18517db96d56Sopenharmony_ci    }
18527db96d56Sopenharmony_ci
18537db96d56Sopenharmony_ci    /* namespace 1: globals */
18547db96d56Sopenharmony_ci    ix = _Py_dict_lookup(globals, key, hash, &value);
18557db96d56Sopenharmony_ci    if (ix == DKIX_ERROR)
18567db96d56Sopenharmony_ci        return NULL;
18577db96d56Sopenharmony_ci    if (ix != DKIX_EMPTY && value != NULL)
18587db96d56Sopenharmony_ci        return value;
18597db96d56Sopenharmony_ci
18607db96d56Sopenharmony_ci    /* namespace 2: builtins */
18617db96d56Sopenharmony_ci    ix = _Py_dict_lookup(builtins, key, hash, &value);
18627db96d56Sopenharmony_ci    assert(ix >= 0 || value == NULL);
18637db96d56Sopenharmony_ci    return value;
18647db96d56Sopenharmony_ci}
18657db96d56Sopenharmony_ci
18667db96d56Sopenharmony_ci/* Consumes references to key and value */
18677db96d56Sopenharmony_ciint
18687db96d56Sopenharmony_ci_PyDict_SetItem_Take2(PyDictObject *mp, PyObject *key, PyObject *value)
18697db96d56Sopenharmony_ci{
18707db96d56Sopenharmony_ci    assert(key);
18717db96d56Sopenharmony_ci    assert(value);
18727db96d56Sopenharmony_ci    assert(PyDict_Check(mp));
18737db96d56Sopenharmony_ci    Py_hash_t hash;
18747db96d56Sopenharmony_ci    if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
18757db96d56Sopenharmony_ci        hash = PyObject_Hash(key);
18767db96d56Sopenharmony_ci        if (hash == -1) {
18777db96d56Sopenharmony_ci            Py_DECREF(key);
18787db96d56Sopenharmony_ci            Py_DECREF(value);
18797db96d56Sopenharmony_ci            return -1;
18807db96d56Sopenharmony_ci        }
18817db96d56Sopenharmony_ci    }
18827db96d56Sopenharmony_ci    if (mp->ma_keys == Py_EMPTY_KEYS) {
18837db96d56Sopenharmony_ci        return insert_to_emptydict(mp, key, hash, value);
18847db96d56Sopenharmony_ci    }
18857db96d56Sopenharmony_ci    /* insertdict() handles any resizing that might be necessary */
18867db96d56Sopenharmony_ci    return insertdict(mp, key, hash, value);
18877db96d56Sopenharmony_ci}
18887db96d56Sopenharmony_ci
18897db96d56Sopenharmony_ci/* CAUTION: PyDict_SetItem() must guarantee that it won't resize the
18907db96d56Sopenharmony_ci * dictionary if it's merely replacing the value for an existing key.
18917db96d56Sopenharmony_ci * This means that it's safe to loop over a dictionary with PyDict_Next()
18927db96d56Sopenharmony_ci * and occasionally replace a value -- but you can't insert new keys or
18937db96d56Sopenharmony_ci * remove them.
18947db96d56Sopenharmony_ci */
18957db96d56Sopenharmony_ciint
18967db96d56Sopenharmony_ciPyDict_SetItem(PyObject *op, PyObject *key, PyObject *value)
18977db96d56Sopenharmony_ci{
18987db96d56Sopenharmony_ci    if (!PyDict_Check(op)) {
18997db96d56Sopenharmony_ci        PyErr_BadInternalCall();
19007db96d56Sopenharmony_ci        return -1;
19017db96d56Sopenharmony_ci    }
19027db96d56Sopenharmony_ci    assert(key);
19037db96d56Sopenharmony_ci    assert(value);
19047db96d56Sopenharmony_ci    Py_INCREF(key);
19057db96d56Sopenharmony_ci    Py_INCREF(value);
19067db96d56Sopenharmony_ci    return _PyDict_SetItem_Take2((PyDictObject *)op, key, value);
19077db96d56Sopenharmony_ci}
19087db96d56Sopenharmony_ci
19097db96d56Sopenharmony_ciint
19107db96d56Sopenharmony_ci_PyDict_SetItem_KnownHash(PyObject *op, PyObject *key, PyObject *value,
19117db96d56Sopenharmony_ci                         Py_hash_t hash)
19127db96d56Sopenharmony_ci{
19137db96d56Sopenharmony_ci    PyDictObject *mp;
19147db96d56Sopenharmony_ci
19157db96d56Sopenharmony_ci    if (!PyDict_Check(op)) {
19167db96d56Sopenharmony_ci        PyErr_BadInternalCall();
19177db96d56Sopenharmony_ci        return -1;
19187db96d56Sopenharmony_ci    }
19197db96d56Sopenharmony_ci    assert(key);
19207db96d56Sopenharmony_ci    assert(value);
19217db96d56Sopenharmony_ci    assert(hash != -1);
19227db96d56Sopenharmony_ci    mp = (PyDictObject *)op;
19237db96d56Sopenharmony_ci
19247db96d56Sopenharmony_ci    Py_INCREF(key);
19257db96d56Sopenharmony_ci    Py_INCREF(value);
19267db96d56Sopenharmony_ci    if (mp->ma_keys == Py_EMPTY_KEYS) {
19277db96d56Sopenharmony_ci        return insert_to_emptydict(mp, key, hash, value);
19287db96d56Sopenharmony_ci    }
19297db96d56Sopenharmony_ci    /* insertdict() handles any resizing that might be necessary */
19307db96d56Sopenharmony_ci    return insertdict(mp, key, hash, value);
19317db96d56Sopenharmony_ci}
19327db96d56Sopenharmony_ci
19337db96d56Sopenharmony_cistatic void
19347db96d56Sopenharmony_cidelete_index_from_values(PyDictValues *values, Py_ssize_t ix)
19357db96d56Sopenharmony_ci{
19367db96d56Sopenharmony_ci    uint8_t *size_ptr = ((uint8_t *)values)-2;
19377db96d56Sopenharmony_ci    int size = *size_ptr;
19387db96d56Sopenharmony_ci    int i;
19397db96d56Sopenharmony_ci    for (i = 1; size_ptr[-i] != ix; i++) {
19407db96d56Sopenharmony_ci        assert(i <= size);
19417db96d56Sopenharmony_ci    }
19427db96d56Sopenharmony_ci    assert(i <= size);
19437db96d56Sopenharmony_ci    for (; i < size; i++) {
19447db96d56Sopenharmony_ci        size_ptr[-i] = size_ptr[-i-1];
19457db96d56Sopenharmony_ci    }
19467db96d56Sopenharmony_ci    *size_ptr = size -1;
19477db96d56Sopenharmony_ci}
19487db96d56Sopenharmony_ci
19497db96d56Sopenharmony_cistatic int
19507db96d56Sopenharmony_cidelitem_common(PyDictObject *mp, Py_hash_t hash, Py_ssize_t ix,
19517db96d56Sopenharmony_ci               PyObject *old_value)
19527db96d56Sopenharmony_ci{
19537db96d56Sopenharmony_ci    PyObject *old_key;
19547db96d56Sopenharmony_ci
19557db96d56Sopenharmony_ci    Py_ssize_t hashpos = lookdict_index(mp->ma_keys, hash, ix);
19567db96d56Sopenharmony_ci    assert(hashpos >= 0);
19577db96d56Sopenharmony_ci
19587db96d56Sopenharmony_ci    mp->ma_used--;
19597db96d56Sopenharmony_ci    mp->ma_version_tag = DICT_NEXT_VERSION();
19607db96d56Sopenharmony_ci    if (mp->ma_values) {
19617db96d56Sopenharmony_ci        assert(old_value == mp->ma_values->values[ix]);
19627db96d56Sopenharmony_ci        mp->ma_values->values[ix] = NULL;
19637db96d56Sopenharmony_ci        assert(ix < SHARED_KEYS_MAX_SIZE);
19647db96d56Sopenharmony_ci        /* Update order */
19657db96d56Sopenharmony_ci        delete_index_from_values(mp->ma_values, ix);
19667db96d56Sopenharmony_ci        ASSERT_CONSISTENT(mp);
19677db96d56Sopenharmony_ci    }
19687db96d56Sopenharmony_ci    else {
19697db96d56Sopenharmony_ci        mp->ma_keys->dk_version = 0;
19707db96d56Sopenharmony_ci        dictkeys_set_index(mp->ma_keys, hashpos, DKIX_DUMMY);
19717db96d56Sopenharmony_ci        if (DK_IS_UNICODE(mp->ma_keys)) {
19727db96d56Sopenharmony_ci            PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(mp->ma_keys)[ix];
19737db96d56Sopenharmony_ci            old_key = ep->me_key;
19747db96d56Sopenharmony_ci            ep->me_key = NULL;
19757db96d56Sopenharmony_ci            ep->me_value = NULL;
19767db96d56Sopenharmony_ci        }
19777db96d56Sopenharmony_ci        else {
19787db96d56Sopenharmony_ci            PyDictKeyEntry *ep = &DK_ENTRIES(mp->ma_keys)[ix];
19797db96d56Sopenharmony_ci            old_key = ep->me_key;
19807db96d56Sopenharmony_ci            ep->me_key = NULL;
19817db96d56Sopenharmony_ci            ep->me_value = NULL;
19827db96d56Sopenharmony_ci            ep->me_hash = 0;
19837db96d56Sopenharmony_ci        }
19847db96d56Sopenharmony_ci        Py_DECREF(old_key);
19857db96d56Sopenharmony_ci    }
19867db96d56Sopenharmony_ci    Py_DECREF(old_value);
19877db96d56Sopenharmony_ci
19887db96d56Sopenharmony_ci    ASSERT_CONSISTENT(mp);
19897db96d56Sopenharmony_ci    return 0;
19907db96d56Sopenharmony_ci}
19917db96d56Sopenharmony_ci
19927db96d56Sopenharmony_ciint
19937db96d56Sopenharmony_ciPyDict_DelItem(PyObject *op, PyObject *key)
19947db96d56Sopenharmony_ci{
19957db96d56Sopenharmony_ci    Py_hash_t hash;
19967db96d56Sopenharmony_ci    assert(key);
19977db96d56Sopenharmony_ci    if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
19987db96d56Sopenharmony_ci        hash = PyObject_Hash(key);
19997db96d56Sopenharmony_ci        if (hash == -1)
20007db96d56Sopenharmony_ci            return -1;
20017db96d56Sopenharmony_ci    }
20027db96d56Sopenharmony_ci
20037db96d56Sopenharmony_ci    return _PyDict_DelItem_KnownHash(op, key, hash);
20047db96d56Sopenharmony_ci}
20057db96d56Sopenharmony_ci
20067db96d56Sopenharmony_ciint
20077db96d56Sopenharmony_ci_PyDict_DelItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
20087db96d56Sopenharmony_ci{
20097db96d56Sopenharmony_ci    Py_ssize_t ix;
20107db96d56Sopenharmony_ci    PyDictObject *mp;
20117db96d56Sopenharmony_ci    PyObject *old_value;
20127db96d56Sopenharmony_ci
20137db96d56Sopenharmony_ci    if (!PyDict_Check(op)) {
20147db96d56Sopenharmony_ci        PyErr_BadInternalCall();
20157db96d56Sopenharmony_ci        return -1;
20167db96d56Sopenharmony_ci    }
20177db96d56Sopenharmony_ci    assert(key);
20187db96d56Sopenharmony_ci    assert(hash != -1);
20197db96d56Sopenharmony_ci    mp = (PyDictObject *)op;
20207db96d56Sopenharmony_ci    ix = _Py_dict_lookup(mp, key, hash, &old_value);
20217db96d56Sopenharmony_ci    if (ix == DKIX_ERROR)
20227db96d56Sopenharmony_ci        return -1;
20237db96d56Sopenharmony_ci    if (ix == DKIX_EMPTY || old_value == NULL) {
20247db96d56Sopenharmony_ci        _PyErr_SetKeyError(key);
20257db96d56Sopenharmony_ci        return -1;
20267db96d56Sopenharmony_ci    }
20277db96d56Sopenharmony_ci
20287db96d56Sopenharmony_ci    return delitem_common(mp, hash, ix, old_value);
20297db96d56Sopenharmony_ci}
20307db96d56Sopenharmony_ci
20317db96d56Sopenharmony_ci/* This function promises that the predicate -> deletion sequence is atomic
20327db96d56Sopenharmony_ci * (i.e. protected by the GIL), assuming the predicate itself doesn't
20337db96d56Sopenharmony_ci * release the GIL.
20347db96d56Sopenharmony_ci */
20357db96d56Sopenharmony_ciint
20367db96d56Sopenharmony_ci_PyDict_DelItemIf(PyObject *op, PyObject *key,
20377db96d56Sopenharmony_ci                  int (*predicate)(PyObject *value))
20387db96d56Sopenharmony_ci{
20397db96d56Sopenharmony_ci    Py_ssize_t hashpos, ix;
20407db96d56Sopenharmony_ci    PyDictObject *mp;
20417db96d56Sopenharmony_ci    Py_hash_t hash;
20427db96d56Sopenharmony_ci    PyObject *old_value;
20437db96d56Sopenharmony_ci    int res;
20447db96d56Sopenharmony_ci
20457db96d56Sopenharmony_ci    if (!PyDict_Check(op)) {
20467db96d56Sopenharmony_ci        PyErr_BadInternalCall();
20477db96d56Sopenharmony_ci        return -1;
20487db96d56Sopenharmony_ci    }
20497db96d56Sopenharmony_ci    assert(key);
20507db96d56Sopenharmony_ci    hash = PyObject_Hash(key);
20517db96d56Sopenharmony_ci    if (hash == -1)
20527db96d56Sopenharmony_ci        return -1;
20537db96d56Sopenharmony_ci    mp = (PyDictObject *)op;
20547db96d56Sopenharmony_ci    ix = _Py_dict_lookup(mp, key, hash, &old_value);
20557db96d56Sopenharmony_ci    if (ix == DKIX_ERROR)
20567db96d56Sopenharmony_ci        return -1;
20577db96d56Sopenharmony_ci    if (ix == DKIX_EMPTY || old_value == NULL) {
20587db96d56Sopenharmony_ci        _PyErr_SetKeyError(key);
20597db96d56Sopenharmony_ci        return -1;
20607db96d56Sopenharmony_ci    }
20617db96d56Sopenharmony_ci
20627db96d56Sopenharmony_ci    res = predicate(old_value);
20637db96d56Sopenharmony_ci    if (res == -1)
20647db96d56Sopenharmony_ci        return -1;
20657db96d56Sopenharmony_ci
20667db96d56Sopenharmony_ci    hashpos = lookdict_index(mp->ma_keys, hash, ix);
20677db96d56Sopenharmony_ci    assert(hashpos >= 0);
20687db96d56Sopenharmony_ci
20697db96d56Sopenharmony_ci    if (res > 0)
20707db96d56Sopenharmony_ci        return delitem_common(mp, hashpos, ix, old_value);
20717db96d56Sopenharmony_ci    else
20727db96d56Sopenharmony_ci        return 0;
20737db96d56Sopenharmony_ci}
20747db96d56Sopenharmony_ci
20757db96d56Sopenharmony_ci
20767db96d56Sopenharmony_civoid
20777db96d56Sopenharmony_ciPyDict_Clear(PyObject *op)
20787db96d56Sopenharmony_ci{
20797db96d56Sopenharmony_ci    PyDictObject *mp;
20807db96d56Sopenharmony_ci    PyDictKeysObject *oldkeys;
20817db96d56Sopenharmony_ci    PyDictValues *oldvalues;
20827db96d56Sopenharmony_ci    Py_ssize_t i, n;
20837db96d56Sopenharmony_ci
20847db96d56Sopenharmony_ci    if (!PyDict_Check(op))
20857db96d56Sopenharmony_ci        return;
20867db96d56Sopenharmony_ci    mp = ((PyDictObject *)op);
20877db96d56Sopenharmony_ci    oldkeys = mp->ma_keys;
20887db96d56Sopenharmony_ci    oldvalues = mp->ma_values;
20897db96d56Sopenharmony_ci    if (oldkeys == Py_EMPTY_KEYS) {
20907db96d56Sopenharmony_ci        return;
20917db96d56Sopenharmony_ci    }
20927db96d56Sopenharmony_ci    /* Empty the dict... */
20937db96d56Sopenharmony_ci    dictkeys_incref(Py_EMPTY_KEYS);
20947db96d56Sopenharmony_ci    mp->ma_keys = Py_EMPTY_KEYS;
20957db96d56Sopenharmony_ci    mp->ma_values = NULL;
20967db96d56Sopenharmony_ci    mp->ma_used = 0;
20977db96d56Sopenharmony_ci    mp->ma_version_tag = DICT_NEXT_VERSION();
20987db96d56Sopenharmony_ci    /* ...then clear the keys and values */
20997db96d56Sopenharmony_ci    if (oldvalues != NULL) {
21007db96d56Sopenharmony_ci        n = oldkeys->dk_nentries;
21017db96d56Sopenharmony_ci        for (i = 0; i < n; i++)
21027db96d56Sopenharmony_ci            Py_CLEAR(oldvalues->values[i]);
21037db96d56Sopenharmony_ci        free_values(oldvalues);
21047db96d56Sopenharmony_ci        dictkeys_decref(oldkeys);
21057db96d56Sopenharmony_ci    }
21067db96d56Sopenharmony_ci    else {
21077db96d56Sopenharmony_ci       assert(oldkeys->dk_refcnt == 1);
21087db96d56Sopenharmony_ci       dictkeys_decref(oldkeys);
21097db96d56Sopenharmony_ci    }
21107db96d56Sopenharmony_ci    ASSERT_CONSISTENT(mp);
21117db96d56Sopenharmony_ci}
21127db96d56Sopenharmony_ci
21137db96d56Sopenharmony_ci/* Internal version of PyDict_Next that returns a hash value in addition
21147db96d56Sopenharmony_ci * to the key and value.
21157db96d56Sopenharmony_ci * Return 1 on success, return 0 when the reached the end of the dictionary
21167db96d56Sopenharmony_ci * (or if op is not a dictionary)
21177db96d56Sopenharmony_ci */
21187db96d56Sopenharmony_ciint
21197db96d56Sopenharmony_ci_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey,
21207db96d56Sopenharmony_ci             PyObject **pvalue, Py_hash_t *phash)
21217db96d56Sopenharmony_ci{
21227db96d56Sopenharmony_ci    Py_ssize_t i;
21237db96d56Sopenharmony_ci    PyDictObject *mp;
21247db96d56Sopenharmony_ci    PyObject *key, *value;
21257db96d56Sopenharmony_ci    Py_hash_t hash;
21267db96d56Sopenharmony_ci
21277db96d56Sopenharmony_ci    if (!PyDict_Check(op))
21287db96d56Sopenharmony_ci        return 0;
21297db96d56Sopenharmony_ci    mp = (PyDictObject *)op;
21307db96d56Sopenharmony_ci    i = *ppos;
21317db96d56Sopenharmony_ci    if (mp->ma_values) {
21327db96d56Sopenharmony_ci        assert(mp->ma_used <= SHARED_KEYS_MAX_SIZE);
21337db96d56Sopenharmony_ci        if (i < 0 || i >= mp->ma_used)
21347db96d56Sopenharmony_ci            return 0;
21357db96d56Sopenharmony_ci        int index = get_index_from_order(mp, i);
21367db96d56Sopenharmony_ci        value = mp->ma_values->values[index];
21377db96d56Sopenharmony_ci
21387db96d56Sopenharmony_ci        key = DK_UNICODE_ENTRIES(mp->ma_keys)[index].me_key;
21397db96d56Sopenharmony_ci        hash = unicode_get_hash(key);
21407db96d56Sopenharmony_ci        assert(value != NULL);
21417db96d56Sopenharmony_ci    }
21427db96d56Sopenharmony_ci    else {
21437db96d56Sopenharmony_ci        Py_ssize_t n = mp->ma_keys->dk_nentries;
21447db96d56Sopenharmony_ci        if (i < 0 || i >= n)
21457db96d56Sopenharmony_ci            return 0;
21467db96d56Sopenharmony_ci        if (DK_IS_UNICODE(mp->ma_keys)) {
21477db96d56Sopenharmony_ci            PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(mp->ma_keys)[i];
21487db96d56Sopenharmony_ci            while (i < n && entry_ptr->me_value == NULL) {
21497db96d56Sopenharmony_ci                entry_ptr++;
21507db96d56Sopenharmony_ci                i++;
21517db96d56Sopenharmony_ci            }
21527db96d56Sopenharmony_ci            if (i >= n)
21537db96d56Sopenharmony_ci                return 0;
21547db96d56Sopenharmony_ci            key = entry_ptr->me_key;
21557db96d56Sopenharmony_ci            hash = unicode_get_hash(entry_ptr->me_key);
21567db96d56Sopenharmony_ci            value = entry_ptr->me_value;
21577db96d56Sopenharmony_ci        }
21587db96d56Sopenharmony_ci        else {
21597db96d56Sopenharmony_ci            PyDictKeyEntry *entry_ptr = &DK_ENTRIES(mp->ma_keys)[i];
21607db96d56Sopenharmony_ci            while (i < n && entry_ptr->me_value == NULL) {
21617db96d56Sopenharmony_ci                entry_ptr++;
21627db96d56Sopenharmony_ci                i++;
21637db96d56Sopenharmony_ci            }
21647db96d56Sopenharmony_ci            if (i >= n)
21657db96d56Sopenharmony_ci                return 0;
21667db96d56Sopenharmony_ci            key = entry_ptr->me_key;
21677db96d56Sopenharmony_ci            hash = entry_ptr->me_hash;
21687db96d56Sopenharmony_ci            value = entry_ptr->me_value;
21697db96d56Sopenharmony_ci        }
21707db96d56Sopenharmony_ci    }
21717db96d56Sopenharmony_ci    *ppos = i+1;
21727db96d56Sopenharmony_ci    if (pkey)
21737db96d56Sopenharmony_ci        *pkey = key;
21747db96d56Sopenharmony_ci    if (pvalue)
21757db96d56Sopenharmony_ci        *pvalue = value;
21767db96d56Sopenharmony_ci    if (phash)
21777db96d56Sopenharmony_ci        *phash = hash;
21787db96d56Sopenharmony_ci    return 1;
21797db96d56Sopenharmony_ci}
21807db96d56Sopenharmony_ci
21817db96d56Sopenharmony_ci/*
21827db96d56Sopenharmony_ci * Iterate over a dict.  Use like so:
21837db96d56Sopenharmony_ci *
21847db96d56Sopenharmony_ci *     Py_ssize_t i;
21857db96d56Sopenharmony_ci *     PyObject *key, *value;
21867db96d56Sopenharmony_ci *     i = 0;   # important!  i should not otherwise be changed by you
21877db96d56Sopenharmony_ci *     while (PyDict_Next(yourdict, &i, &key, &value)) {
21887db96d56Sopenharmony_ci *         Refer to borrowed references in key and value.
21897db96d56Sopenharmony_ci *     }
21907db96d56Sopenharmony_ci *
21917db96d56Sopenharmony_ci * Return 1 on success, return 0 when the reached the end of the dictionary
21927db96d56Sopenharmony_ci * (or if op is not a dictionary)
21937db96d56Sopenharmony_ci *
21947db96d56Sopenharmony_ci * CAUTION:  In general, it isn't safe to use PyDict_Next in a loop that
21957db96d56Sopenharmony_ci * mutates the dict.  One exception:  it is safe if the loop merely changes
21967db96d56Sopenharmony_ci * the values associated with the keys (but doesn't insert new keys or
21977db96d56Sopenharmony_ci * delete keys), via PyDict_SetItem().
21987db96d56Sopenharmony_ci */
21997db96d56Sopenharmony_ciint
22007db96d56Sopenharmony_ciPyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue)
22017db96d56Sopenharmony_ci{
22027db96d56Sopenharmony_ci    return _PyDict_Next(op, ppos, pkey, pvalue, NULL);
22037db96d56Sopenharmony_ci}
22047db96d56Sopenharmony_ci
22057db96d56Sopenharmony_ci/* Internal version of dict.pop(). */
22067db96d56Sopenharmony_ciPyObject *
22077db96d56Sopenharmony_ci_PyDict_Pop_KnownHash(PyObject *dict, PyObject *key, Py_hash_t hash, PyObject *deflt)
22087db96d56Sopenharmony_ci{
22097db96d56Sopenharmony_ci    Py_ssize_t ix;
22107db96d56Sopenharmony_ci    PyObject *old_value;
22117db96d56Sopenharmony_ci    PyDictObject *mp;
22127db96d56Sopenharmony_ci
22137db96d56Sopenharmony_ci    assert(PyDict_Check(dict));
22147db96d56Sopenharmony_ci    mp = (PyDictObject *)dict;
22157db96d56Sopenharmony_ci
22167db96d56Sopenharmony_ci    if (mp->ma_used == 0) {
22177db96d56Sopenharmony_ci        if (deflt) {
22187db96d56Sopenharmony_ci            Py_INCREF(deflt);
22197db96d56Sopenharmony_ci            return deflt;
22207db96d56Sopenharmony_ci        }
22217db96d56Sopenharmony_ci        _PyErr_SetKeyError(key);
22227db96d56Sopenharmony_ci        return NULL;
22237db96d56Sopenharmony_ci    }
22247db96d56Sopenharmony_ci    ix = _Py_dict_lookup(mp, key, hash, &old_value);
22257db96d56Sopenharmony_ci    if (ix == DKIX_ERROR)
22267db96d56Sopenharmony_ci        return NULL;
22277db96d56Sopenharmony_ci    if (ix == DKIX_EMPTY || old_value == NULL) {
22287db96d56Sopenharmony_ci        if (deflt) {
22297db96d56Sopenharmony_ci            Py_INCREF(deflt);
22307db96d56Sopenharmony_ci            return deflt;
22317db96d56Sopenharmony_ci        }
22327db96d56Sopenharmony_ci        _PyErr_SetKeyError(key);
22337db96d56Sopenharmony_ci        return NULL;
22347db96d56Sopenharmony_ci    }
22357db96d56Sopenharmony_ci    assert(old_value != NULL);
22367db96d56Sopenharmony_ci    Py_INCREF(old_value);
22377db96d56Sopenharmony_ci    delitem_common(mp, hash, ix, old_value);
22387db96d56Sopenharmony_ci
22397db96d56Sopenharmony_ci    ASSERT_CONSISTENT(mp);
22407db96d56Sopenharmony_ci    return old_value;
22417db96d56Sopenharmony_ci}
22427db96d56Sopenharmony_ci
22437db96d56Sopenharmony_ciPyObject *
22447db96d56Sopenharmony_ci_PyDict_Pop(PyObject *dict, PyObject *key, PyObject *deflt)
22457db96d56Sopenharmony_ci{
22467db96d56Sopenharmony_ci    Py_hash_t hash;
22477db96d56Sopenharmony_ci
22487db96d56Sopenharmony_ci    if (((PyDictObject *)dict)->ma_used == 0) {
22497db96d56Sopenharmony_ci        if (deflt) {
22507db96d56Sopenharmony_ci            Py_INCREF(deflt);
22517db96d56Sopenharmony_ci            return deflt;
22527db96d56Sopenharmony_ci        }
22537db96d56Sopenharmony_ci        _PyErr_SetKeyError(key);
22547db96d56Sopenharmony_ci        return NULL;
22557db96d56Sopenharmony_ci    }
22567db96d56Sopenharmony_ci    if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
22577db96d56Sopenharmony_ci        hash = PyObject_Hash(key);
22587db96d56Sopenharmony_ci        if (hash == -1)
22597db96d56Sopenharmony_ci            return NULL;
22607db96d56Sopenharmony_ci    }
22617db96d56Sopenharmony_ci    return _PyDict_Pop_KnownHash(dict, key, hash, deflt);
22627db96d56Sopenharmony_ci}
22637db96d56Sopenharmony_ci
22647db96d56Sopenharmony_ci/* Internal version of dict.from_keys().  It is subclass-friendly. */
22657db96d56Sopenharmony_ciPyObject *
22667db96d56Sopenharmony_ci_PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
22677db96d56Sopenharmony_ci{
22687db96d56Sopenharmony_ci    PyObject *it;       /* iter(iterable) */
22697db96d56Sopenharmony_ci    PyObject *key;
22707db96d56Sopenharmony_ci    PyObject *d;
22717db96d56Sopenharmony_ci    int status;
22727db96d56Sopenharmony_ci
22737db96d56Sopenharmony_ci    d = _PyObject_CallNoArgs(cls);
22747db96d56Sopenharmony_ci    if (d == NULL)
22757db96d56Sopenharmony_ci        return NULL;
22767db96d56Sopenharmony_ci
22777db96d56Sopenharmony_ci    if (PyDict_CheckExact(d) && ((PyDictObject *)d)->ma_used == 0) {
22787db96d56Sopenharmony_ci        if (PyDict_CheckExact(iterable)) {
22797db96d56Sopenharmony_ci            PyDictObject *mp = (PyDictObject *)d;
22807db96d56Sopenharmony_ci            PyObject *oldvalue;
22817db96d56Sopenharmony_ci            Py_ssize_t pos = 0;
22827db96d56Sopenharmony_ci            PyObject *key;
22837db96d56Sopenharmony_ci            Py_hash_t hash;
22847db96d56Sopenharmony_ci
22857db96d56Sopenharmony_ci            int unicode = DK_IS_UNICODE(((PyDictObject*)iterable)->ma_keys);
22867db96d56Sopenharmony_ci            if (dictresize(mp, estimate_log2_keysize(PyDict_GET_SIZE(iterable)), unicode)) {
22877db96d56Sopenharmony_ci                Py_DECREF(d);
22887db96d56Sopenharmony_ci                return NULL;
22897db96d56Sopenharmony_ci            }
22907db96d56Sopenharmony_ci
22917db96d56Sopenharmony_ci            while (_PyDict_Next(iterable, &pos, &key, &oldvalue, &hash)) {
22927db96d56Sopenharmony_ci                Py_INCREF(key);
22937db96d56Sopenharmony_ci                Py_INCREF(value);
22947db96d56Sopenharmony_ci                if (insertdict(mp, key, hash, value)) {
22957db96d56Sopenharmony_ci                    Py_DECREF(d);
22967db96d56Sopenharmony_ci                    return NULL;
22977db96d56Sopenharmony_ci                }
22987db96d56Sopenharmony_ci            }
22997db96d56Sopenharmony_ci            return d;
23007db96d56Sopenharmony_ci        }
23017db96d56Sopenharmony_ci        if (PyAnySet_CheckExact(iterable)) {
23027db96d56Sopenharmony_ci            PyDictObject *mp = (PyDictObject *)d;
23037db96d56Sopenharmony_ci            Py_ssize_t pos = 0;
23047db96d56Sopenharmony_ci            PyObject *key;
23057db96d56Sopenharmony_ci            Py_hash_t hash;
23067db96d56Sopenharmony_ci
23077db96d56Sopenharmony_ci            if (dictresize(mp, estimate_log2_keysize(PySet_GET_SIZE(iterable)), 0)) {
23087db96d56Sopenharmony_ci                Py_DECREF(d);
23097db96d56Sopenharmony_ci                return NULL;
23107db96d56Sopenharmony_ci            }
23117db96d56Sopenharmony_ci
23127db96d56Sopenharmony_ci            while (_PySet_NextEntry(iterable, &pos, &key, &hash)) {
23137db96d56Sopenharmony_ci                Py_INCREF(key);
23147db96d56Sopenharmony_ci                Py_INCREF(value);
23157db96d56Sopenharmony_ci                if (insertdict(mp, key, hash, value)) {
23167db96d56Sopenharmony_ci                    Py_DECREF(d);
23177db96d56Sopenharmony_ci                    return NULL;
23187db96d56Sopenharmony_ci                }
23197db96d56Sopenharmony_ci            }
23207db96d56Sopenharmony_ci            return d;
23217db96d56Sopenharmony_ci        }
23227db96d56Sopenharmony_ci    }
23237db96d56Sopenharmony_ci
23247db96d56Sopenharmony_ci    it = PyObject_GetIter(iterable);
23257db96d56Sopenharmony_ci    if (it == NULL){
23267db96d56Sopenharmony_ci        Py_DECREF(d);
23277db96d56Sopenharmony_ci        return NULL;
23287db96d56Sopenharmony_ci    }
23297db96d56Sopenharmony_ci
23307db96d56Sopenharmony_ci    if (PyDict_CheckExact(d)) {
23317db96d56Sopenharmony_ci        while ((key = PyIter_Next(it)) != NULL) {
23327db96d56Sopenharmony_ci            status = PyDict_SetItem(d, key, value);
23337db96d56Sopenharmony_ci            Py_DECREF(key);
23347db96d56Sopenharmony_ci            if (status < 0)
23357db96d56Sopenharmony_ci                goto Fail;
23367db96d56Sopenharmony_ci        }
23377db96d56Sopenharmony_ci    } else {
23387db96d56Sopenharmony_ci        while ((key = PyIter_Next(it)) != NULL) {
23397db96d56Sopenharmony_ci            status = PyObject_SetItem(d, key, value);
23407db96d56Sopenharmony_ci            Py_DECREF(key);
23417db96d56Sopenharmony_ci            if (status < 0)
23427db96d56Sopenharmony_ci                goto Fail;
23437db96d56Sopenharmony_ci        }
23447db96d56Sopenharmony_ci    }
23457db96d56Sopenharmony_ci
23467db96d56Sopenharmony_ci    if (PyErr_Occurred())
23477db96d56Sopenharmony_ci        goto Fail;
23487db96d56Sopenharmony_ci    Py_DECREF(it);
23497db96d56Sopenharmony_ci    return d;
23507db96d56Sopenharmony_ci
23517db96d56Sopenharmony_ciFail:
23527db96d56Sopenharmony_ci    Py_DECREF(it);
23537db96d56Sopenharmony_ci    Py_DECREF(d);
23547db96d56Sopenharmony_ci    return NULL;
23557db96d56Sopenharmony_ci}
23567db96d56Sopenharmony_ci
23577db96d56Sopenharmony_ci/* Methods */
23587db96d56Sopenharmony_ci
23597db96d56Sopenharmony_cistatic void
23607db96d56Sopenharmony_cidict_dealloc(PyDictObject *mp)
23617db96d56Sopenharmony_ci{
23627db96d56Sopenharmony_ci    PyDictValues *values = mp->ma_values;
23637db96d56Sopenharmony_ci    PyDictKeysObject *keys = mp->ma_keys;
23647db96d56Sopenharmony_ci    Py_ssize_t i, n;
23657db96d56Sopenharmony_ci
23667db96d56Sopenharmony_ci    /* bpo-31095: UnTrack is needed before calling any callbacks */
23677db96d56Sopenharmony_ci    PyObject_GC_UnTrack(mp);
23687db96d56Sopenharmony_ci    Py_TRASHCAN_BEGIN(mp, dict_dealloc)
23697db96d56Sopenharmony_ci    if (values != NULL) {
23707db96d56Sopenharmony_ci        for (i = 0, n = mp->ma_keys->dk_nentries; i < n; i++) {
23717db96d56Sopenharmony_ci            Py_XDECREF(values->values[i]);
23727db96d56Sopenharmony_ci        }
23737db96d56Sopenharmony_ci        free_values(values);
23747db96d56Sopenharmony_ci        dictkeys_decref(keys);
23757db96d56Sopenharmony_ci    }
23767db96d56Sopenharmony_ci    else if (keys != NULL) {
23777db96d56Sopenharmony_ci        assert(keys->dk_refcnt == 1 || keys == Py_EMPTY_KEYS);
23787db96d56Sopenharmony_ci        dictkeys_decref(keys);
23797db96d56Sopenharmony_ci    }
23807db96d56Sopenharmony_ci#if PyDict_MAXFREELIST > 0
23817db96d56Sopenharmony_ci    struct _Py_dict_state *state = get_dict_state();
23827db96d56Sopenharmony_ci#ifdef Py_DEBUG
23837db96d56Sopenharmony_ci    // new_dict() must not be called after _PyDict_Fini()
23847db96d56Sopenharmony_ci    assert(state->numfree != -1);
23857db96d56Sopenharmony_ci#endif
23867db96d56Sopenharmony_ci    if (state->numfree < PyDict_MAXFREELIST && Py_IS_TYPE(mp, &PyDict_Type)) {
23877db96d56Sopenharmony_ci        state->free_list[state->numfree++] = mp;
23887db96d56Sopenharmony_ci        OBJECT_STAT_INC(to_freelist);
23897db96d56Sopenharmony_ci    }
23907db96d56Sopenharmony_ci    else
23917db96d56Sopenharmony_ci#endif
23927db96d56Sopenharmony_ci    {
23937db96d56Sopenharmony_ci        Py_TYPE(mp)->tp_free((PyObject *)mp);
23947db96d56Sopenharmony_ci    }
23957db96d56Sopenharmony_ci    Py_TRASHCAN_END
23967db96d56Sopenharmony_ci}
23977db96d56Sopenharmony_ci
23987db96d56Sopenharmony_ci
23997db96d56Sopenharmony_cistatic PyObject *
24007db96d56Sopenharmony_cidict_repr(PyDictObject *mp)
24017db96d56Sopenharmony_ci{
24027db96d56Sopenharmony_ci    Py_ssize_t i;
24037db96d56Sopenharmony_ci    PyObject *key = NULL, *value = NULL;
24047db96d56Sopenharmony_ci    _PyUnicodeWriter writer;
24057db96d56Sopenharmony_ci    int first;
24067db96d56Sopenharmony_ci
24077db96d56Sopenharmony_ci    i = Py_ReprEnter((PyObject *)mp);
24087db96d56Sopenharmony_ci    if (i != 0) {
24097db96d56Sopenharmony_ci        return i > 0 ? PyUnicode_FromString("{...}") : NULL;
24107db96d56Sopenharmony_ci    }
24117db96d56Sopenharmony_ci
24127db96d56Sopenharmony_ci    if (mp->ma_used == 0) {
24137db96d56Sopenharmony_ci        Py_ReprLeave((PyObject *)mp);
24147db96d56Sopenharmony_ci        return PyUnicode_FromString("{}");
24157db96d56Sopenharmony_ci    }
24167db96d56Sopenharmony_ci
24177db96d56Sopenharmony_ci    _PyUnicodeWriter_Init(&writer);
24187db96d56Sopenharmony_ci    writer.overallocate = 1;
24197db96d56Sopenharmony_ci    /* "{" + "1: 2" + ", 3: 4" * (len - 1) + "}" */
24207db96d56Sopenharmony_ci    writer.min_length = 1 + 4 + (2 + 4) * (mp->ma_used - 1) + 1;
24217db96d56Sopenharmony_ci
24227db96d56Sopenharmony_ci    if (_PyUnicodeWriter_WriteChar(&writer, '{') < 0)
24237db96d56Sopenharmony_ci        goto error;
24247db96d56Sopenharmony_ci
24257db96d56Sopenharmony_ci    /* Do repr() on each key+value pair, and insert ": " between them.
24267db96d56Sopenharmony_ci       Note that repr may mutate the dict. */
24277db96d56Sopenharmony_ci    i = 0;
24287db96d56Sopenharmony_ci    first = 1;
24297db96d56Sopenharmony_ci    while (PyDict_Next((PyObject *)mp, &i, &key, &value)) {
24307db96d56Sopenharmony_ci        PyObject *s;
24317db96d56Sopenharmony_ci        int res;
24327db96d56Sopenharmony_ci
24337db96d56Sopenharmony_ci        /* Prevent repr from deleting key or value during key format. */
24347db96d56Sopenharmony_ci        Py_INCREF(key);
24357db96d56Sopenharmony_ci        Py_INCREF(value);
24367db96d56Sopenharmony_ci
24377db96d56Sopenharmony_ci        if (!first) {
24387db96d56Sopenharmony_ci            if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0)
24397db96d56Sopenharmony_ci                goto error;
24407db96d56Sopenharmony_ci        }
24417db96d56Sopenharmony_ci        first = 0;
24427db96d56Sopenharmony_ci
24437db96d56Sopenharmony_ci        s = PyObject_Repr(key);
24447db96d56Sopenharmony_ci        if (s == NULL)
24457db96d56Sopenharmony_ci            goto error;
24467db96d56Sopenharmony_ci        res = _PyUnicodeWriter_WriteStr(&writer, s);
24477db96d56Sopenharmony_ci        Py_DECREF(s);
24487db96d56Sopenharmony_ci        if (res < 0)
24497db96d56Sopenharmony_ci            goto error;
24507db96d56Sopenharmony_ci
24517db96d56Sopenharmony_ci        if (_PyUnicodeWriter_WriteASCIIString(&writer, ": ", 2) < 0)
24527db96d56Sopenharmony_ci            goto error;
24537db96d56Sopenharmony_ci
24547db96d56Sopenharmony_ci        s = PyObject_Repr(value);
24557db96d56Sopenharmony_ci        if (s == NULL)
24567db96d56Sopenharmony_ci            goto error;
24577db96d56Sopenharmony_ci        res = _PyUnicodeWriter_WriteStr(&writer, s);
24587db96d56Sopenharmony_ci        Py_DECREF(s);
24597db96d56Sopenharmony_ci        if (res < 0)
24607db96d56Sopenharmony_ci            goto error;
24617db96d56Sopenharmony_ci
24627db96d56Sopenharmony_ci        Py_CLEAR(key);
24637db96d56Sopenharmony_ci        Py_CLEAR(value);
24647db96d56Sopenharmony_ci    }
24657db96d56Sopenharmony_ci
24667db96d56Sopenharmony_ci    writer.overallocate = 0;
24677db96d56Sopenharmony_ci    if (_PyUnicodeWriter_WriteChar(&writer, '}') < 0)
24687db96d56Sopenharmony_ci        goto error;
24697db96d56Sopenharmony_ci
24707db96d56Sopenharmony_ci    Py_ReprLeave((PyObject *)mp);
24717db96d56Sopenharmony_ci
24727db96d56Sopenharmony_ci    return _PyUnicodeWriter_Finish(&writer);
24737db96d56Sopenharmony_ci
24747db96d56Sopenharmony_cierror:
24757db96d56Sopenharmony_ci    Py_ReprLeave((PyObject *)mp);
24767db96d56Sopenharmony_ci    _PyUnicodeWriter_Dealloc(&writer);
24777db96d56Sopenharmony_ci    Py_XDECREF(key);
24787db96d56Sopenharmony_ci    Py_XDECREF(value);
24797db96d56Sopenharmony_ci    return NULL;
24807db96d56Sopenharmony_ci}
24817db96d56Sopenharmony_ci
24827db96d56Sopenharmony_cistatic Py_ssize_t
24837db96d56Sopenharmony_cidict_length(PyDictObject *mp)
24847db96d56Sopenharmony_ci{
24857db96d56Sopenharmony_ci    return mp->ma_used;
24867db96d56Sopenharmony_ci}
24877db96d56Sopenharmony_ci
24887db96d56Sopenharmony_cistatic PyObject *
24897db96d56Sopenharmony_cidict_subscript(PyDictObject *mp, PyObject *key)
24907db96d56Sopenharmony_ci{
24917db96d56Sopenharmony_ci    Py_ssize_t ix;
24927db96d56Sopenharmony_ci    Py_hash_t hash;
24937db96d56Sopenharmony_ci    PyObject *value;
24947db96d56Sopenharmony_ci
24957db96d56Sopenharmony_ci    if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
24967db96d56Sopenharmony_ci        hash = PyObject_Hash(key);
24977db96d56Sopenharmony_ci        if (hash == -1)
24987db96d56Sopenharmony_ci            return NULL;
24997db96d56Sopenharmony_ci    }
25007db96d56Sopenharmony_ci    ix = _Py_dict_lookup(mp, key, hash, &value);
25017db96d56Sopenharmony_ci    if (ix == DKIX_ERROR)
25027db96d56Sopenharmony_ci        return NULL;
25037db96d56Sopenharmony_ci    if (ix == DKIX_EMPTY || value == NULL) {
25047db96d56Sopenharmony_ci        if (!PyDict_CheckExact(mp)) {
25057db96d56Sopenharmony_ci            /* Look up __missing__ method if we're a subclass. */
25067db96d56Sopenharmony_ci            PyObject *missing, *res;
25077db96d56Sopenharmony_ci            missing = _PyObject_LookupSpecial(
25087db96d56Sopenharmony_ci                    (PyObject *)mp, &_Py_ID(__missing__));
25097db96d56Sopenharmony_ci            if (missing != NULL) {
25107db96d56Sopenharmony_ci                res = PyObject_CallOneArg(missing, key);
25117db96d56Sopenharmony_ci                Py_DECREF(missing);
25127db96d56Sopenharmony_ci                return res;
25137db96d56Sopenharmony_ci            }
25147db96d56Sopenharmony_ci            else if (PyErr_Occurred())
25157db96d56Sopenharmony_ci                return NULL;
25167db96d56Sopenharmony_ci        }
25177db96d56Sopenharmony_ci        _PyErr_SetKeyError(key);
25187db96d56Sopenharmony_ci        return NULL;
25197db96d56Sopenharmony_ci    }
25207db96d56Sopenharmony_ci    Py_INCREF(value);
25217db96d56Sopenharmony_ci    return value;
25227db96d56Sopenharmony_ci}
25237db96d56Sopenharmony_ci
25247db96d56Sopenharmony_cistatic int
25257db96d56Sopenharmony_cidict_ass_sub(PyDictObject *mp, PyObject *v, PyObject *w)
25267db96d56Sopenharmony_ci{
25277db96d56Sopenharmony_ci    if (w == NULL)
25287db96d56Sopenharmony_ci        return PyDict_DelItem((PyObject *)mp, v);
25297db96d56Sopenharmony_ci    else
25307db96d56Sopenharmony_ci        return PyDict_SetItem((PyObject *)mp, v, w);
25317db96d56Sopenharmony_ci}
25327db96d56Sopenharmony_ci
25337db96d56Sopenharmony_cistatic PyMappingMethods dict_as_mapping = {
25347db96d56Sopenharmony_ci    (lenfunc)dict_length, /*mp_length*/
25357db96d56Sopenharmony_ci    (binaryfunc)dict_subscript, /*mp_subscript*/
25367db96d56Sopenharmony_ci    (objobjargproc)dict_ass_sub, /*mp_ass_subscript*/
25377db96d56Sopenharmony_ci};
25387db96d56Sopenharmony_ci
25397db96d56Sopenharmony_cistatic PyObject *
25407db96d56Sopenharmony_cidict_keys(PyDictObject *mp)
25417db96d56Sopenharmony_ci{
25427db96d56Sopenharmony_ci    PyObject *v;
25437db96d56Sopenharmony_ci    Py_ssize_t n;
25447db96d56Sopenharmony_ci
25457db96d56Sopenharmony_ci  again:
25467db96d56Sopenharmony_ci    n = mp->ma_used;
25477db96d56Sopenharmony_ci    v = PyList_New(n);
25487db96d56Sopenharmony_ci    if (v == NULL)
25497db96d56Sopenharmony_ci        return NULL;
25507db96d56Sopenharmony_ci    if (n != mp->ma_used) {
25517db96d56Sopenharmony_ci        /* Durnit.  The allocations caused the dict to resize.
25527db96d56Sopenharmony_ci         * Just start over, this shouldn't normally happen.
25537db96d56Sopenharmony_ci         */
25547db96d56Sopenharmony_ci        Py_DECREF(v);
25557db96d56Sopenharmony_ci        goto again;
25567db96d56Sopenharmony_ci    }
25577db96d56Sopenharmony_ci
25587db96d56Sopenharmony_ci    /* Nothing we do below makes any function calls. */
25597db96d56Sopenharmony_ci    Py_ssize_t j = 0, pos = 0;
25607db96d56Sopenharmony_ci    PyObject *key;
25617db96d56Sopenharmony_ci    while (_PyDict_Next((PyObject*)mp, &pos, &key, NULL, NULL)) {
25627db96d56Sopenharmony_ci        assert(j < n);
25637db96d56Sopenharmony_ci        Py_INCREF(key);
25647db96d56Sopenharmony_ci        PyList_SET_ITEM(v, j, key);
25657db96d56Sopenharmony_ci        j++;
25667db96d56Sopenharmony_ci    }
25677db96d56Sopenharmony_ci    assert(j == n);
25687db96d56Sopenharmony_ci    return v;
25697db96d56Sopenharmony_ci}
25707db96d56Sopenharmony_ci
25717db96d56Sopenharmony_cistatic PyObject *
25727db96d56Sopenharmony_cidict_values(PyDictObject *mp)
25737db96d56Sopenharmony_ci{
25747db96d56Sopenharmony_ci    PyObject *v;
25757db96d56Sopenharmony_ci    Py_ssize_t n;
25767db96d56Sopenharmony_ci
25777db96d56Sopenharmony_ci  again:
25787db96d56Sopenharmony_ci    n = mp->ma_used;
25797db96d56Sopenharmony_ci    v = PyList_New(n);
25807db96d56Sopenharmony_ci    if (v == NULL)
25817db96d56Sopenharmony_ci        return NULL;
25827db96d56Sopenharmony_ci    if (n != mp->ma_used) {
25837db96d56Sopenharmony_ci        /* Durnit.  The allocations caused the dict to resize.
25847db96d56Sopenharmony_ci         * Just start over, this shouldn't normally happen.
25857db96d56Sopenharmony_ci         */
25867db96d56Sopenharmony_ci        Py_DECREF(v);
25877db96d56Sopenharmony_ci        goto again;
25887db96d56Sopenharmony_ci    }
25897db96d56Sopenharmony_ci
25907db96d56Sopenharmony_ci    /* Nothing we do below makes any function calls. */
25917db96d56Sopenharmony_ci    Py_ssize_t j = 0, pos = 0;
25927db96d56Sopenharmony_ci    PyObject *value;
25937db96d56Sopenharmony_ci    while (_PyDict_Next((PyObject*)mp, &pos, NULL, &value, NULL)) {
25947db96d56Sopenharmony_ci        assert(j < n);
25957db96d56Sopenharmony_ci        Py_INCREF(value);
25967db96d56Sopenharmony_ci        PyList_SET_ITEM(v, j, value);
25977db96d56Sopenharmony_ci        j++;
25987db96d56Sopenharmony_ci    }
25997db96d56Sopenharmony_ci    assert(j == n);
26007db96d56Sopenharmony_ci    return v;
26017db96d56Sopenharmony_ci}
26027db96d56Sopenharmony_ci
26037db96d56Sopenharmony_cistatic PyObject *
26047db96d56Sopenharmony_cidict_items(PyDictObject *mp)
26057db96d56Sopenharmony_ci{
26067db96d56Sopenharmony_ci    PyObject *v;
26077db96d56Sopenharmony_ci    Py_ssize_t i, n;
26087db96d56Sopenharmony_ci    PyObject *item;
26097db96d56Sopenharmony_ci
26107db96d56Sopenharmony_ci    /* Preallocate the list of tuples, to avoid allocations during
26117db96d56Sopenharmony_ci     * the loop over the items, which could trigger GC, which
26127db96d56Sopenharmony_ci     * could resize the dict. :-(
26137db96d56Sopenharmony_ci     */
26147db96d56Sopenharmony_ci  again:
26157db96d56Sopenharmony_ci    n = mp->ma_used;
26167db96d56Sopenharmony_ci    v = PyList_New(n);
26177db96d56Sopenharmony_ci    if (v == NULL)
26187db96d56Sopenharmony_ci        return NULL;
26197db96d56Sopenharmony_ci    for (i = 0; i < n; i++) {
26207db96d56Sopenharmony_ci        item = PyTuple_New(2);
26217db96d56Sopenharmony_ci        if (item == NULL) {
26227db96d56Sopenharmony_ci            Py_DECREF(v);
26237db96d56Sopenharmony_ci            return NULL;
26247db96d56Sopenharmony_ci        }
26257db96d56Sopenharmony_ci        PyList_SET_ITEM(v, i, item);
26267db96d56Sopenharmony_ci    }
26277db96d56Sopenharmony_ci    if (n != mp->ma_used) {
26287db96d56Sopenharmony_ci        /* Durnit.  The allocations caused the dict to resize.
26297db96d56Sopenharmony_ci         * Just start over, this shouldn't normally happen.
26307db96d56Sopenharmony_ci         */
26317db96d56Sopenharmony_ci        Py_DECREF(v);
26327db96d56Sopenharmony_ci        goto again;
26337db96d56Sopenharmony_ci    }
26347db96d56Sopenharmony_ci
26357db96d56Sopenharmony_ci    /* Nothing we do below makes any function calls. */
26367db96d56Sopenharmony_ci    Py_ssize_t j = 0, pos = 0;
26377db96d56Sopenharmony_ci    PyObject *key, *value;
26387db96d56Sopenharmony_ci    while (_PyDict_Next((PyObject*)mp, &pos, &key, &value, NULL)) {
26397db96d56Sopenharmony_ci        assert(j < n);
26407db96d56Sopenharmony_ci        PyObject *item = PyList_GET_ITEM(v, j);
26417db96d56Sopenharmony_ci        Py_INCREF(key);
26427db96d56Sopenharmony_ci        PyTuple_SET_ITEM(item, 0, key);
26437db96d56Sopenharmony_ci        Py_INCREF(value);
26447db96d56Sopenharmony_ci        PyTuple_SET_ITEM(item, 1, value);
26457db96d56Sopenharmony_ci        j++;
26467db96d56Sopenharmony_ci    }
26477db96d56Sopenharmony_ci    assert(j == n);
26487db96d56Sopenharmony_ci    return v;
26497db96d56Sopenharmony_ci}
26507db96d56Sopenharmony_ci
26517db96d56Sopenharmony_ci/*[clinic input]
26527db96d56Sopenharmony_ci@classmethod
26537db96d56Sopenharmony_cidict.fromkeys
26547db96d56Sopenharmony_ci    iterable: object
26557db96d56Sopenharmony_ci    value: object=None
26567db96d56Sopenharmony_ci    /
26577db96d56Sopenharmony_ci
26587db96d56Sopenharmony_ciCreate a new dictionary with keys from iterable and values set to value.
26597db96d56Sopenharmony_ci[clinic start generated code]*/
26607db96d56Sopenharmony_ci
26617db96d56Sopenharmony_cistatic PyObject *
26627db96d56Sopenharmony_cidict_fromkeys_impl(PyTypeObject *type, PyObject *iterable, PyObject *value)
26637db96d56Sopenharmony_ci/*[clinic end generated code: output=8fb98e4b10384999 input=382ba4855d0f74c3]*/
26647db96d56Sopenharmony_ci{
26657db96d56Sopenharmony_ci    return _PyDict_FromKeys((PyObject *)type, iterable, value);
26667db96d56Sopenharmony_ci}
26677db96d56Sopenharmony_ci
26687db96d56Sopenharmony_ci/* Single-arg dict update; used by dict_update_common and operators. */
26697db96d56Sopenharmony_cistatic int
26707db96d56Sopenharmony_cidict_update_arg(PyObject *self, PyObject *arg)
26717db96d56Sopenharmony_ci{
26727db96d56Sopenharmony_ci    if (PyDict_CheckExact(arg)) {
26737db96d56Sopenharmony_ci        return PyDict_Merge(self, arg, 1);
26747db96d56Sopenharmony_ci    }
26757db96d56Sopenharmony_ci    PyObject *func;
26767db96d56Sopenharmony_ci    if (_PyObject_LookupAttr(arg, &_Py_ID(keys), &func) < 0) {
26777db96d56Sopenharmony_ci        return -1;
26787db96d56Sopenharmony_ci    }
26797db96d56Sopenharmony_ci    if (func != NULL) {
26807db96d56Sopenharmony_ci        Py_DECREF(func);
26817db96d56Sopenharmony_ci        return PyDict_Merge(self, arg, 1);
26827db96d56Sopenharmony_ci    }
26837db96d56Sopenharmony_ci    return PyDict_MergeFromSeq2(self, arg, 1);
26847db96d56Sopenharmony_ci}
26857db96d56Sopenharmony_ci
26867db96d56Sopenharmony_cistatic int
26877db96d56Sopenharmony_cidict_update_common(PyObject *self, PyObject *args, PyObject *kwds,
26887db96d56Sopenharmony_ci                   const char *methname)
26897db96d56Sopenharmony_ci{
26907db96d56Sopenharmony_ci    PyObject *arg = NULL;
26917db96d56Sopenharmony_ci    int result = 0;
26927db96d56Sopenharmony_ci
26937db96d56Sopenharmony_ci    if (!PyArg_UnpackTuple(args, methname, 0, 1, &arg)) {
26947db96d56Sopenharmony_ci        result = -1;
26957db96d56Sopenharmony_ci    }
26967db96d56Sopenharmony_ci    else if (arg != NULL) {
26977db96d56Sopenharmony_ci        result = dict_update_arg(self, arg);
26987db96d56Sopenharmony_ci    }
26997db96d56Sopenharmony_ci
27007db96d56Sopenharmony_ci    if (result == 0 && kwds != NULL) {
27017db96d56Sopenharmony_ci        if (PyArg_ValidateKeywordArguments(kwds))
27027db96d56Sopenharmony_ci            result = PyDict_Merge(self, kwds, 1);
27037db96d56Sopenharmony_ci        else
27047db96d56Sopenharmony_ci            result = -1;
27057db96d56Sopenharmony_ci    }
27067db96d56Sopenharmony_ci    return result;
27077db96d56Sopenharmony_ci}
27087db96d56Sopenharmony_ci
27097db96d56Sopenharmony_ci/* Note: dict.update() uses the METH_VARARGS|METH_KEYWORDS calling convention.
27107db96d56Sopenharmony_ci   Using METH_FASTCALL|METH_KEYWORDS would make dict.update(**dict2) calls
27117db96d56Sopenharmony_ci   slower, see the issue #29312. */
27127db96d56Sopenharmony_cistatic PyObject *
27137db96d56Sopenharmony_cidict_update(PyObject *self, PyObject *args, PyObject *kwds)
27147db96d56Sopenharmony_ci{
27157db96d56Sopenharmony_ci    if (dict_update_common(self, args, kwds, "update") != -1)
27167db96d56Sopenharmony_ci        Py_RETURN_NONE;
27177db96d56Sopenharmony_ci    return NULL;
27187db96d56Sopenharmony_ci}
27197db96d56Sopenharmony_ci
27207db96d56Sopenharmony_ci/* Update unconditionally replaces existing items.
27217db96d56Sopenharmony_ci   Merge has a 3rd argument 'override'; if set, it acts like Update,
27227db96d56Sopenharmony_ci   otherwise it leaves existing items unchanged.
27237db96d56Sopenharmony_ci
27247db96d56Sopenharmony_ci   PyDict_{Update,Merge} update/merge from a mapping object.
27257db96d56Sopenharmony_ci
27267db96d56Sopenharmony_ci   PyDict_MergeFromSeq2 updates/merges from any iterable object
27277db96d56Sopenharmony_ci   producing iterable objects of length 2.
27287db96d56Sopenharmony_ci*/
27297db96d56Sopenharmony_ci
27307db96d56Sopenharmony_ciint
27317db96d56Sopenharmony_ciPyDict_MergeFromSeq2(PyObject *d, PyObject *seq2, int override)
27327db96d56Sopenharmony_ci{
27337db96d56Sopenharmony_ci    PyObject *it;       /* iter(seq2) */
27347db96d56Sopenharmony_ci    Py_ssize_t i;       /* index into seq2 of current element */
27357db96d56Sopenharmony_ci    PyObject *item;     /* seq2[i] */
27367db96d56Sopenharmony_ci    PyObject *fast;     /* item as a 2-tuple or 2-list */
27377db96d56Sopenharmony_ci
27387db96d56Sopenharmony_ci    assert(d != NULL);
27397db96d56Sopenharmony_ci    assert(PyDict_Check(d));
27407db96d56Sopenharmony_ci    assert(seq2 != NULL);
27417db96d56Sopenharmony_ci
27427db96d56Sopenharmony_ci    it = PyObject_GetIter(seq2);
27437db96d56Sopenharmony_ci    if (it == NULL)
27447db96d56Sopenharmony_ci        return -1;
27457db96d56Sopenharmony_ci
27467db96d56Sopenharmony_ci    for (i = 0; ; ++i) {
27477db96d56Sopenharmony_ci        PyObject *key, *value;
27487db96d56Sopenharmony_ci        Py_ssize_t n;
27497db96d56Sopenharmony_ci
27507db96d56Sopenharmony_ci        fast = NULL;
27517db96d56Sopenharmony_ci        item = PyIter_Next(it);
27527db96d56Sopenharmony_ci        if (item == NULL) {
27537db96d56Sopenharmony_ci            if (PyErr_Occurred())
27547db96d56Sopenharmony_ci                goto Fail;
27557db96d56Sopenharmony_ci            break;
27567db96d56Sopenharmony_ci        }
27577db96d56Sopenharmony_ci
27587db96d56Sopenharmony_ci        /* Convert item to sequence, and verify length 2. */
27597db96d56Sopenharmony_ci        fast = PySequence_Fast(item, "");
27607db96d56Sopenharmony_ci        if (fast == NULL) {
27617db96d56Sopenharmony_ci            if (PyErr_ExceptionMatches(PyExc_TypeError))
27627db96d56Sopenharmony_ci                PyErr_Format(PyExc_TypeError,
27637db96d56Sopenharmony_ci                    "cannot convert dictionary update "
27647db96d56Sopenharmony_ci                    "sequence element #%zd to a sequence",
27657db96d56Sopenharmony_ci                    i);
27667db96d56Sopenharmony_ci            goto Fail;
27677db96d56Sopenharmony_ci        }
27687db96d56Sopenharmony_ci        n = PySequence_Fast_GET_SIZE(fast);
27697db96d56Sopenharmony_ci        if (n != 2) {
27707db96d56Sopenharmony_ci            PyErr_Format(PyExc_ValueError,
27717db96d56Sopenharmony_ci                         "dictionary update sequence element #%zd "
27727db96d56Sopenharmony_ci                         "has length %zd; 2 is required",
27737db96d56Sopenharmony_ci                         i, n);
27747db96d56Sopenharmony_ci            goto Fail;
27757db96d56Sopenharmony_ci        }
27767db96d56Sopenharmony_ci
27777db96d56Sopenharmony_ci        /* Update/merge with this (key, value) pair. */
27787db96d56Sopenharmony_ci        key = PySequence_Fast_GET_ITEM(fast, 0);
27797db96d56Sopenharmony_ci        value = PySequence_Fast_GET_ITEM(fast, 1);
27807db96d56Sopenharmony_ci        Py_INCREF(key);
27817db96d56Sopenharmony_ci        Py_INCREF(value);
27827db96d56Sopenharmony_ci        if (override) {
27837db96d56Sopenharmony_ci            if (PyDict_SetItem(d, key, value) < 0) {
27847db96d56Sopenharmony_ci                Py_DECREF(key);
27857db96d56Sopenharmony_ci                Py_DECREF(value);
27867db96d56Sopenharmony_ci                goto Fail;
27877db96d56Sopenharmony_ci            }
27887db96d56Sopenharmony_ci        }
27897db96d56Sopenharmony_ci        else {
27907db96d56Sopenharmony_ci            if (PyDict_SetDefault(d, key, value) == NULL) {
27917db96d56Sopenharmony_ci                Py_DECREF(key);
27927db96d56Sopenharmony_ci                Py_DECREF(value);
27937db96d56Sopenharmony_ci                goto Fail;
27947db96d56Sopenharmony_ci            }
27957db96d56Sopenharmony_ci        }
27967db96d56Sopenharmony_ci
27977db96d56Sopenharmony_ci        Py_DECREF(key);
27987db96d56Sopenharmony_ci        Py_DECREF(value);
27997db96d56Sopenharmony_ci        Py_DECREF(fast);
28007db96d56Sopenharmony_ci        Py_DECREF(item);
28017db96d56Sopenharmony_ci    }
28027db96d56Sopenharmony_ci
28037db96d56Sopenharmony_ci    i = 0;
28047db96d56Sopenharmony_ci    ASSERT_CONSISTENT(d);
28057db96d56Sopenharmony_ci    goto Return;
28067db96d56Sopenharmony_ciFail:
28077db96d56Sopenharmony_ci    Py_XDECREF(item);
28087db96d56Sopenharmony_ci    Py_XDECREF(fast);
28097db96d56Sopenharmony_ci    i = -1;
28107db96d56Sopenharmony_ciReturn:
28117db96d56Sopenharmony_ci    Py_DECREF(it);
28127db96d56Sopenharmony_ci    return Py_SAFE_DOWNCAST(i, Py_ssize_t, int);
28137db96d56Sopenharmony_ci}
28147db96d56Sopenharmony_ci
28157db96d56Sopenharmony_cistatic int
28167db96d56Sopenharmony_cidict_merge(PyObject *a, PyObject *b, int override)
28177db96d56Sopenharmony_ci{
28187db96d56Sopenharmony_ci    PyDictObject *mp, *other;
28197db96d56Sopenharmony_ci
28207db96d56Sopenharmony_ci    assert(0 <= override && override <= 2);
28217db96d56Sopenharmony_ci
28227db96d56Sopenharmony_ci    /* We accept for the argument either a concrete dictionary object,
28237db96d56Sopenharmony_ci     * or an abstract "mapping" object.  For the former, we can do
28247db96d56Sopenharmony_ci     * things quite efficiently.  For the latter, we only require that
28257db96d56Sopenharmony_ci     * PyMapping_Keys() and PyObject_GetItem() be supported.
28267db96d56Sopenharmony_ci     */
28277db96d56Sopenharmony_ci    if (a == NULL || !PyDict_Check(a) || b == NULL) {
28287db96d56Sopenharmony_ci        PyErr_BadInternalCall();
28297db96d56Sopenharmony_ci        return -1;
28307db96d56Sopenharmony_ci    }
28317db96d56Sopenharmony_ci    mp = (PyDictObject*)a;
28327db96d56Sopenharmony_ci    if (PyDict_Check(b) && (Py_TYPE(b)->tp_iter == (getiterfunc)dict_iter)) {
28337db96d56Sopenharmony_ci        other = (PyDictObject*)b;
28347db96d56Sopenharmony_ci        if (other == mp || other->ma_used == 0)
28357db96d56Sopenharmony_ci            /* a.update(a) or a.update({}); nothing to do */
28367db96d56Sopenharmony_ci            return 0;
28377db96d56Sopenharmony_ci        if (mp->ma_used == 0) {
28387db96d56Sopenharmony_ci            /* Since the target dict is empty, PyDict_GetItem()
28397db96d56Sopenharmony_ci             * always returns NULL.  Setting override to 1
28407db96d56Sopenharmony_ci             * skips the unnecessary test.
28417db96d56Sopenharmony_ci             */
28427db96d56Sopenharmony_ci            override = 1;
28437db96d56Sopenharmony_ci            PyDictKeysObject *okeys = other->ma_keys;
28447db96d56Sopenharmony_ci
28457db96d56Sopenharmony_ci            // If other is clean, combined, and just allocated, just clone it.
28467db96d56Sopenharmony_ci            if (other->ma_values == NULL &&
28477db96d56Sopenharmony_ci                    other->ma_used == okeys->dk_nentries &&
28487db96d56Sopenharmony_ci                    (DK_LOG_SIZE(okeys) == PyDict_LOG_MINSIZE ||
28497db96d56Sopenharmony_ci                     USABLE_FRACTION(DK_SIZE(okeys)/2) < other->ma_used)) {
28507db96d56Sopenharmony_ci                PyDictKeysObject *keys = clone_combined_dict_keys(other);
28517db96d56Sopenharmony_ci                if (keys == NULL) {
28527db96d56Sopenharmony_ci                    return -1;
28537db96d56Sopenharmony_ci                }
28547db96d56Sopenharmony_ci
28557db96d56Sopenharmony_ci                dictkeys_decref(mp->ma_keys);
28567db96d56Sopenharmony_ci                mp->ma_keys = keys;
28577db96d56Sopenharmony_ci                if (mp->ma_values != NULL) {
28587db96d56Sopenharmony_ci                    free_values(mp->ma_values);
28597db96d56Sopenharmony_ci                    mp->ma_values = NULL;
28607db96d56Sopenharmony_ci                }
28617db96d56Sopenharmony_ci
28627db96d56Sopenharmony_ci                mp->ma_used = other->ma_used;
28637db96d56Sopenharmony_ci                mp->ma_version_tag = DICT_NEXT_VERSION();
28647db96d56Sopenharmony_ci                ASSERT_CONSISTENT(mp);
28657db96d56Sopenharmony_ci
28667db96d56Sopenharmony_ci                if (_PyObject_GC_IS_TRACKED(other) && !_PyObject_GC_IS_TRACKED(mp)) {
28677db96d56Sopenharmony_ci                    /* Maintain tracking. */
28687db96d56Sopenharmony_ci                    _PyObject_GC_TRACK(mp);
28697db96d56Sopenharmony_ci                }
28707db96d56Sopenharmony_ci
28717db96d56Sopenharmony_ci                return 0;
28727db96d56Sopenharmony_ci            }
28737db96d56Sopenharmony_ci        }
28747db96d56Sopenharmony_ci        /* Do one big resize at the start, rather than
28757db96d56Sopenharmony_ci         * incrementally resizing as we insert new items.  Expect
28767db96d56Sopenharmony_ci         * that there will be no (or few) overlapping keys.
28777db96d56Sopenharmony_ci         */
28787db96d56Sopenharmony_ci        if (USABLE_FRACTION(DK_SIZE(mp->ma_keys)) < other->ma_used) {
28797db96d56Sopenharmony_ci            int unicode = DK_IS_UNICODE(other->ma_keys);
28807db96d56Sopenharmony_ci            if (dictresize(mp, estimate_log2_keysize(mp->ma_used + other->ma_used), unicode)) {
28817db96d56Sopenharmony_ci               return -1;
28827db96d56Sopenharmony_ci            }
28837db96d56Sopenharmony_ci        }
28847db96d56Sopenharmony_ci
28857db96d56Sopenharmony_ci        Py_ssize_t orig_size = other->ma_keys->dk_nentries;
28867db96d56Sopenharmony_ci        Py_ssize_t pos = 0;
28877db96d56Sopenharmony_ci        Py_hash_t hash;
28887db96d56Sopenharmony_ci        PyObject *key, *value;
28897db96d56Sopenharmony_ci
28907db96d56Sopenharmony_ci        while (_PyDict_Next((PyObject*)other, &pos, &key, &value, &hash)) {
28917db96d56Sopenharmony_ci            int err = 0;
28927db96d56Sopenharmony_ci            Py_INCREF(key);
28937db96d56Sopenharmony_ci            Py_INCREF(value);
28947db96d56Sopenharmony_ci            if (override == 1) {
28957db96d56Sopenharmony_ci                Py_INCREF(key);
28967db96d56Sopenharmony_ci                Py_INCREF(value);
28977db96d56Sopenharmony_ci                err = insertdict(mp, key, hash, value);
28987db96d56Sopenharmony_ci            }
28997db96d56Sopenharmony_ci            else {
29007db96d56Sopenharmony_ci                err = _PyDict_Contains_KnownHash(a, key, hash);
29017db96d56Sopenharmony_ci                if (err == 0) {
29027db96d56Sopenharmony_ci                    Py_INCREF(key);
29037db96d56Sopenharmony_ci                    Py_INCREF(value);
29047db96d56Sopenharmony_ci                    err = insertdict(mp, key, hash, value);
29057db96d56Sopenharmony_ci                }
29067db96d56Sopenharmony_ci                else if (err > 0) {
29077db96d56Sopenharmony_ci                    if (override != 0) {
29087db96d56Sopenharmony_ci                        _PyErr_SetKeyError(key);
29097db96d56Sopenharmony_ci                        Py_DECREF(value);
29107db96d56Sopenharmony_ci                        Py_DECREF(key);
29117db96d56Sopenharmony_ci                        return -1;
29127db96d56Sopenharmony_ci                    }
29137db96d56Sopenharmony_ci                    err = 0;
29147db96d56Sopenharmony_ci                }
29157db96d56Sopenharmony_ci            }
29167db96d56Sopenharmony_ci            Py_DECREF(value);
29177db96d56Sopenharmony_ci            Py_DECREF(key);
29187db96d56Sopenharmony_ci            if (err != 0)
29197db96d56Sopenharmony_ci                return -1;
29207db96d56Sopenharmony_ci
29217db96d56Sopenharmony_ci            if (orig_size != other->ma_keys->dk_nentries) {
29227db96d56Sopenharmony_ci                PyErr_SetString(PyExc_RuntimeError,
29237db96d56Sopenharmony_ci                        "dict mutated during update");
29247db96d56Sopenharmony_ci                return -1;
29257db96d56Sopenharmony_ci            }
29267db96d56Sopenharmony_ci        }
29277db96d56Sopenharmony_ci    }
29287db96d56Sopenharmony_ci    else {
29297db96d56Sopenharmony_ci        /* Do it the generic, slower way */
29307db96d56Sopenharmony_ci        PyObject *keys = PyMapping_Keys(b);
29317db96d56Sopenharmony_ci        PyObject *iter;
29327db96d56Sopenharmony_ci        PyObject *key, *value;
29337db96d56Sopenharmony_ci        int status;
29347db96d56Sopenharmony_ci
29357db96d56Sopenharmony_ci        if (keys == NULL)
29367db96d56Sopenharmony_ci            /* Docstring says this is equivalent to E.keys() so
29377db96d56Sopenharmony_ci             * if E doesn't have a .keys() method we want
29387db96d56Sopenharmony_ci             * AttributeError to percolate up.  Might as well
29397db96d56Sopenharmony_ci             * do the same for any other error.
29407db96d56Sopenharmony_ci             */
29417db96d56Sopenharmony_ci            return -1;
29427db96d56Sopenharmony_ci
29437db96d56Sopenharmony_ci        iter = PyObject_GetIter(keys);
29447db96d56Sopenharmony_ci        Py_DECREF(keys);
29457db96d56Sopenharmony_ci        if (iter == NULL)
29467db96d56Sopenharmony_ci            return -1;
29477db96d56Sopenharmony_ci
29487db96d56Sopenharmony_ci        for (key = PyIter_Next(iter); key; key = PyIter_Next(iter)) {
29497db96d56Sopenharmony_ci            if (override != 1) {
29507db96d56Sopenharmony_ci                status = PyDict_Contains(a, key);
29517db96d56Sopenharmony_ci                if (status != 0) {
29527db96d56Sopenharmony_ci                    if (status > 0) {
29537db96d56Sopenharmony_ci                        if (override == 0) {
29547db96d56Sopenharmony_ci                            Py_DECREF(key);
29557db96d56Sopenharmony_ci                            continue;
29567db96d56Sopenharmony_ci                        }
29577db96d56Sopenharmony_ci                        _PyErr_SetKeyError(key);
29587db96d56Sopenharmony_ci                    }
29597db96d56Sopenharmony_ci                    Py_DECREF(key);
29607db96d56Sopenharmony_ci                    Py_DECREF(iter);
29617db96d56Sopenharmony_ci                    return -1;
29627db96d56Sopenharmony_ci                }
29637db96d56Sopenharmony_ci            }
29647db96d56Sopenharmony_ci            value = PyObject_GetItem(b, key);
29657db96d56Sopenharmony_ci            if (value == NULL) {
29667db96d56Sopenharmony_ci                Py_DECREF(iter);
29677db96d56Sopenharmony_ci                Py_DECREF(key);
29687db96d56Sopenharmony_ci                return -1;
29697db96d56Sopenharmony_ci            }
29707db96d56Sopenharmony_ci            status = PyDict_SetItem(a, key, value);
29717db96d56Sopenharmony_ci            Py_DECREF(key);
29727db96d56Sopenharmony_ci            Py_DECREF(value);
29737db96d56Sopenharmony_ci            if (status < 0) {
29747db96d56Sopenharmony_ci                Py_DECREF(iter);
29757db96d56Sopenharmony_ci                return -1;
29767db96d56Sopenharmony_ci            }
29777db96d56Sopenharmony_ci        }
29787db96d56Sopenharmony_ci        Py_DECREF(iter);
29797db96d56Sopenharmony_ci        if (PyErr_Occurred())
29807db96d56Sopenharmony_ci            /* Iterator completed, via error */
29817db96d56Sopenharmony_ci            return -1;
29827db96d56Sopenharmony_ci    }
29837db96d56Sopenharmony_ci    ASSERT_CONSISTENT(a);
29847db96d56Sopenharmony_ci    return 0;
29857db96d56Sopenharmony_ci}
29867db96d56Sopenharmony_ci
29877db96d56Sopenharmony_ciint
29887db96d56Sopenharmony_ciPyDict_Update(PyObject *a, PyObject *b)
29897db96d56Sopenharmony_ci{
29907db96d56Sopenharmony_ci    return dict_merge(a, b, 1);
29917db96d56Sopenharmony_ci}
29927db96d56Sopenharmony_ci
29937db96d56Sopenharmony_ciint
29947db96d56Sopenharmony_ciPyDict_Merge(PyObject *a, PyObject *b, int override)
29957db96d56Sopenharmony_ci{
29967db96d56Sopenharmony_ci    /* XXX Deprecate override not in (0, 1). */
29977db96d56Sopenharmony_ci    return dict_merge(a, b, override != 0);
29987db96d56Sopenharmony_ci}
29997db96d56Sopenharmony_ci
30007db96d56Sopenharmony_ciint
30017db96d56Sopenharmony_ci_PyDict_MergeEx(PyObject *a, PyObject *b, int override)
30027db96d56Sopenharmony_ci{
30037db96d56Sopenharmony_ci    return dict_merge(a, b, override);
30047db96d56Sopenharmony_ci}
30057db96d56Sopenharmony_ci
30067db96d56Sopenharmony_cistatic PyObject *
30077db96d56Sopenharmony_cidict_copy(PyDictObject *mp, PyObject *Py_UNUSED(ignored))
30087db96d56Sopenharmony_ci{
30097db96d56Sopenharmony_ci    return PyDict_Copy((PyObject*)mp);
30107db96d56Sopenharmony_ci}
30117db96d56Sopenharmony_ci
30127db96d56Sopenharmony_ciPyObject *
30137db96d56Sopenharmony_ciPyDict_Copy(PyObject *o)
30147db96d56Sopenharmony_ci{
30157db96d56Sopenharmony_ci    PyObject *copy;
30167db96d56Sopenharmony_ci    PyDictObject *mp;
30177db96d56Sopenharmony_ci    Py_ssize_t i, n;
30187db96d56Sopenharmony_ci
30197db96d56Sopenharmony_ci    if (o == NULL || !PyDict_Check(o)) {
30207db96d56Sopenharmony_ci        PyErr_BadInternalCall();
30217db96d56Sopenharmony_ci        return NULL;
30227db96d56Sopenharmony_ci    }
30237db96d56Sopenharmony_ci
30247db96d56Sopenharmony_ci    mp = (PyDictObject *)o;
30257db96d56Sopenharmony_ci    if (mp->ma_used == 0) {
30267db96d56Sopenharmony_ci        /* The dict is empty; just return a new dict. */
30277db96d56Sopenharmony_ci        return PyDict_New();
30287db96d56Sopenharmony_ci    }
30297db96d56Sopenharmony_ci
30307db96d56Sopenharmony_ci    if (_PyDict_HasSplitTable(mp)) {
30317db96d56Sopenharmony_ci        PyDictObject *split_copy;
30327db96d56Sopenharmony_ci        Py_ssize_t size = shared_keys_usable_size(mp->ma_keys);
30337db96d56Sopenharmony_ci        PyDictValues *newvalues;
30347db96d56Sopenharmony_ci        newvalues = new_values(size);
30357db96d56Sopenharmony_ci        if (newvalues == NULL)
30367db96d56Sopenharmony_ci            return PyErr_NoMemory();
30377db96d56Sopenharmony_ci        split_copy = PyObject_GC_New(PyDictObject, &PyDict_Type);
30387db96d56Sopenharmony_ci        if (split_copy == NULL) {
30397db96d56Sopenharmony_ci            free_values(newvalues);
30407db96d56Sopenharmony_ci            return NULL;
30417db96d56Sopenharmony_ci        }
30427db96d56Sopenharmony_ci        size_t prefix_size = ((uint8_t *)newvalues)[-1];
30437db96d56Sopenharmony_ci        memcpy(((char *)newvalues)-prefix_size, ((char *)mp->ma_values)-prefix_size, prefix_size-1);
30447db96d56Sopenharmony_ci        split_copy->ma_values = newvalues;
30457db96d56Sopenharmony_ci        split_copy->ma_keys = mp->ma_keys;
30467db96d56Sopenharmony_ci        split_copy->ma_used = mp->ma_used;
30477db96d56Sopenharmony_ci        split_copy->ma_version_tag = DICT_NEXT_VERSION();
30487db96d56Sopenharmony_ci        dictkeys_incref(mp->ma_keys);
30497db96d56Sopenharmony_ci        for (i = 0, n = size; i < n; i++) {
30507db96d56Sopenharmony_ci            PyObject *value = mp->ma_values->values[i];
30517db96d56Sopenharmony_ci            Py_XINCREF(value);
30527db96d56Sopenharmony_ci            split_copy->ma_values->values[i] = value;
30537db96d56Sopenharmony_ci        }
30547db96d56Sopenharmony_ci        if (_PyObject_GC_IS_TRACKED(mp))
30557db96d56Sopenharmony_ci            _PyObject_GC_TRACK(split_copy);
30567db96d56Sopenharmony_ci        return (PyObject *)split_copy;
30577db96d56Sopenharmony_ci    }
30587db96d56Sopenharmony_ci
30597db96d56Sopenharmony_ci    if (Py_TYPE(mp)->tp_iter == (getiterfunc)dict_iter &&
30607db96d56Sopenharmony_ci            mp->ma_values == NULL &&
30617db96d56Sopenharmony_ci            (mp->ma_used >= (mp->ma_keys->dk_nentries * 2) / 3))
30627db96d56Sopenharmony_ci    {
30637db96d56Sopenharmony_ci        /* Use fast-copy if:
30647db96d56Sopenharmony_ci
30657db96d56Sopenharmony_ci           (1) type(mp) doesn't override tp_iter; and
30667db96d56Sopenharmony_ci
30677db96d56Sopenharmony_ci           (2) 'mp' is not a split-dict; and
30687db96d56Sopenharmony_ci
30697db96d56Sopenharmony_ci           (3) if 'mp' is non-compact ('del' operation does not resize dicts),
30707db96d56Sopenharmony_ci               do fast-copy only if it has at most 1/3 non-used keys.
30717db96d56Sopenharmony_ci
30727db96d56Sopenharmony_ci           The last condition (3) is important to guard against a pathological
30737db96d56Sopenharmony_ci           case when a large dict is almost emptied with multiple del/pop
30747db96d56Sopenharmony_ci           operations and copied after that.  In cases like this, we defer to
30757db96d56Sopenharmony_ci           PyDict_Merge, which produces a compacted copy.
30767db96d56Sopenharmony_ci        */
30777db96d56Sopenharmony_ci        PyDictKeysObject *keys = clone_combined_dict_keys(mp);
30787db96d56Sopenharmony_ci        if (keys == NULL) {
30797db96d56Sopenharmony_ci            return NULL;
30807db96d56Sopenharmony_ci        }
30817db96d56Sopenharmony_ci        PyDictObject *new = (PyDictObject *)new_dict(keys, NULL, 0, 0);
30827db96d56Sopenharmony_ci        if (new == NULL) {
30837db96d56Sopenharmony_ci            /* In case of an error, `new_dict()` takes care of
30847db96d56Sopenharmony_ci               cleaning up `keys`. */
30857db96d56Sopenharmony_ci            return NULL;
30867db96d56Sopenharmony_ci        }
30877db96d56Sopenharmony_ci
30887db96d56Sopenharmony_ci        new->ma_used = mp->ma_used;
30897db96d56Sopenharmony_ci        ASSERT_CONSISTENT(new);
30907db96d56Sopenharmony_ci        if (_PyObject_GC_IS_TRACKED(mp)) {
30917db96d56Sopenharmony_ci            /* Maintain tracking. */
30927db96d56Sopenharmony_ci            _PyObject_GC_TRACK(new);
30937db96d56Sopenharmony_ci        }
30947db96d56Sopenharmony_ci
30957db96d56Sopenharmony_ci        return (PyObject *)new;
30967db96d56Sopenharmony_ci    }
30977db96d56Sopenharmony_ci
30987db96d56Sopenharmony_ci    copy = PyDict_New();
30997db96d56Sopenharmony_ci    if (copy == NULL)
31007db96d56Sopenharmony_ci        return NULL;
31017db96d56Sopenharmony_ci    if (dict_merge(copy, o, 1) == 0)
31027db96d56Sopenharmony_ci        return copy;
31037db96d56Sopenharmony_ci    Py_DECREF(copy);
31047db96d56Sopenharmony_ci    return NULL;
31057db96d56Sopenharmony_ci}
31067db96d56Sopenharmony_ci
31077db96d56Sopenharmony_ciPy_ssize_t
31087db96d56Sopenharmony_ciPyDict_Size(PyObject *mp)
31097db96d56Sopenharmony_ci{
31107db96d56Sopenharmony_ci    if (mp == NULL || !PyDict_Check(mp)) {
31117db96d56Sopenharmony_ci        PyErr_BadInternalCall();
31127db96d56Sopenharmony_ci        return -1;
31137db96d56Sopenharmony_ci    }
31147db96d56Sopenharmony_ci    return ((PyDictObject *)mp)->ma_used;
31157db96d56Sopenharmony_ci}
31167db96d56Sopenharmony_ci
31177db96d56Sopenharmony_ciPyObject *
31187db96d56Sopenharmony_ciPyDict_Keys(PyObject *mp)
31197db96d56Sopenharmony_ci{
31207db96d56Sopenharmony_ci    if (mp == NULL || !PyDict_Check(mp)) {
31217db96d56Sopenharmony_ci        PyErr_BadInternalCall();
31227db96d56Sopenharmony_ci        return NULL;
31237db96d56Sopenharmony_ci    }
31247db96d56Sopenharmony_ci    return dict_keys((PyDictObject *)mp);
31257db96d56Sopenharmony_ci}
31267db96d56Sopenharmony_ci
31277db96d56Sopenharmony_ciPyObject *
31287db96d56Sopenharmony_ciPyDict_Values(PyObject *mp)
31297db96d56Sopenharmony_ci{
31307db96d56Sopenharmony_ci    if (mp == NULL || !PyDict_Check(mp)) {
31317db96d56Sopenharmony_ci        PyErr_BadInternalCall();
31327db96d56Sopenharmony_ci        return NULL;
31337db96d56Sopenharmony_ci    }
31347db96d56Sopenharmony_ci    return dict_values((PyDictObject *)mp);
31357db96d56Sopenharmony_ci}
31367db96d56Sopenharmony_ci
31377db96d56Sopenharmony_ciPyObject *
31387db96d56Sopenharmony_ciPyDict_Items(PyObject *mp)
31397db96d56Sopenharmony_ci{
31407db96d56Sopenharmony_ci    if (mp == NULL || !PyDict_Check(mp)) {
31417db96d56Sopenharmony_ci        PyErr_BadInternalCall();
31427db96d56Sopenharmony_ci        return NULL;
31437db96d56Sopenharmony_ci    }
31447db96d56Sopenharmony_ci    return dict_items((PyDictObject *)mp);
31457db96d56Sopenharmony_ci}
31467db96d56Sopenharmony_ci
31477db96d56Sopenharmony_ci/* Return 1 if dicts equal, 0 if not, -1 if error.
31487db96d56Sopenharmony_ci * Gets out as soon as any difference is detected.
31497db96d56Sopenharmony_ci * Uses only Py_EQ comparison.
31507db96d56Sopenharmony_ci */
31517db96d56Sopenharmony_cistatic int
31527db96d56Sopenharmony_cidict_equal(PyDictObject *a, PyDictObject *b)
31537db96d56Sopenharmony_ci{
31547db96d56Sopenharmony_ci    Py_ssize_t i;
31557db96d56Sopenharmony_ci
31567db96d56Sopenharmony_ci    if (a->ma_used != b->ma_used)
31577db96d56Sopenharmony_ci        /* can't be equal if # of entries differ */
31587db96d56Sopenharmony_ci        return 0;
31597db96d56Sopenharmony_ci    /* Same # of entries -- check all of 'em.  Exit early on any diff. */
31607db96d56Sopenharmony_ci    for (i = 0; i < a->ma_keys->dk_nentries; i++) {
31617db96d56Sopenharmony_ci        PyObject *key, *aval;
31627db96d56Sopenharmony_ci        Py_hash_t hash;
31637db96d56Sopenharmony_ci        if (DK_IS_UNICODE(a->ma_keys)) {
31647db96d56Sopenharmony_ci            PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(a->ma_keys)[i];
31657db96d56Sopenharmony_ci            key = ep->me_key;
31667db96d56Sopenharmony_ci            if (key == NULL) {
31677db96d56Sopenharmony_ci                continue;
31687db96d56Sopenharmony_ci            }
31697db96d56Sopenharmony_ci            hash = unicode_get_hash(key);
31707db96d56Sopenharmony_ci            if (a->ma_values)
31717db96d56Sopenharmony_ci                aval = a->ma_values->values[i];
31727db96d56Sopenharmony_ci            else
31737db96d56Sopenharmony_ci                aval = ep->me_value;
31747db96d56Sopenharmony_ci        }
31757db96d56Sopenharmony_ci        else {
31767db96d56Sopenharmony_ci            PyDictKeyEntry *ep = &DK_ENTRIES(a->ma_keys)[i];
31777db96d56Sopenharmony_ci            key = ep->me_key;
31787db96d56Sopenharmony_ci            aval = ep->me_value;
31797db96d56Sopenharmony_ci            hash = ep->me_hash;
31807db96d56Sopenharmony_ci        }
31817db96d56Sopenharmony_ci        if (aval != NULL) {
31827db96d56Sopenharmony_ci            int cmp;
31837db96d56Sopenharmony_ci            PyObject *bval;
31847db96d56Sopenharmony_ci            /* temporarily bump aval's refcount to ensure it stays
31857db96d56Sopenharmony_ci               alive until we're done with it */
31867db96d56Sopenharmony_ci            Py_INCREF(aval);
31877db96d56Sopenharmony_ci            /* ditto for key */
31887db96d56Sopenharmony_ci            Py_INCREF(key);
31897db96d56Sopenharmony_ci            /* reuse the known hash value */
31907db96d56Sopenharmony_ci            _Py_dict_lookup(b, key, hash, &bval);
31917db96d56Sopenharmony_ci            if (bval == NULL) {
31927db96d56Sopenharmony_ci                Py_DECREF(key);
31937db96d56Sopenharmony_ci                Py_DECREF(aval);
31947db96d56Sopenharmony_ci                if (PyErr_Occurred())
31957db96d56Sopenharmony_ci                    return -1;
31967db96d56Sopenharmony_ci                return 0;
31977db96d56Sopenharmony_ci            }
31987db96d56Sopenharmony_ci            Py_INCREF(bval);
31997db96d56Sopenharmony_ci            cmp = PyObject_RichCompareBool(aval, bval, Py_EQ);
32007db96d56Sopenharmony_ci            Py_DECREF(key);
32017db96d56Sopenharmony_ci            Py_DECREF(aval);
32027db96d56Sopenharmony_ci            Py_DECREF(bval);
32037db96d56Sopenharmony_ci            if (cmp <= 0)  /* error or not equal */
32047db96d56Sopenharmony_ci                return cmp;
32057db96d56Sopenharmony_ci        }
32067db96d56Sopenharmony_ci    }
32077db96d56Sopenharmony_ci    return 1;
32087db96d56Sopenharmony_ci}
32097db96d56Sopenharmony_ci
32107db96d56Sopenharmony_cistatic PyObject *
32117db96d56Sopenharmony_cidict_richcompare(PyObject *v, PyObject *w, int op)
32127db96d56Sopenharmony_ci{
32137db96d56Sopenharmony_ci    int cmp;
32147db96d56Sopenharmony_ci    PyObject *res;
32157db96d56Sopenharmony_ci
32167db96d56Sopenharmony_ci    if (!PyDict_Check(v) || !PyDict_Check(w)) {
32177db96d56Sopenharmony_ci        res = Py_NotImplemented;
32187db96d56Sopenharmony_ci    }
32197db96d56Sopenharmony_ci    else if (op == Py_EQ || op == Py_NE) {
32207db96d56Sopenharmony_ci        cmp = dict_equal((PyDictObject *)v, (PyDictObject *)w);
32217db96d56Sopenharmony_ci        if (cmp < 0)
32227db96d56Sopenharmony_ci            return NULL;
32237db96d56Sopenharmony_ci        res = (cmp == (op == Py_EQ)) ? Py_True : Py_False;
32247db96d56Sopenharmony_ci    }
32257db96d56Sopenharmony_ci    else
32267db96d56Sopenharmony_ci        res = Py_NotImplemented;
32277db96d56Sopenharmony_ci    Py_INCREF(res);
32287db96d56Sopenharmony_ci    return res;
32297db96d56Sopenharmony_ci}
32307db96d56Sopenharmony_ci
32317db96d56Sopenharmony_ci/*[clinic input]
32327db96d56Sopenharmony_ci
32337db96d56Sopenharmony_ci@coexist
32347db96d56Sopenharmony_cidict.__contains__
32357db96d56Sopenharmony_ci
32367db96d56Sopenharmony_ci  key: object
32377db96d56Sopenharmony_ci  /
32387db96d56Sopenharmony_ci
32397db96d56Sopenharmony_ciTrue if the dictionary has the specified key, else False.
32407db96d56Sopenharmony_ci[clinic start generated code]*/
32417db96d56Sopenharmony_ci
32427db96d56Sopenharmony_cistatic PyObject *
32437db96d56Sopenharmony_cidict___contains__(PyDictObject *self, PyObject *key)
32447db96d56Sopenharmony_ci/*[clinic end generated code: output=a3d03db709ed6e6b input=fe1cb42ad831e820]*/
32457db96d56Sopenharmony_ci{
32467db96d56Sopenharmony_ci    register PyDictObject *mp = self;
32477db96d56Sopenharmony_ci    Py_hash_t hash;
32487db96d56Sopenharmony_ci    Py_ssize_t ix;
32497db96d56Sopenharmony_ci    PyObject *value;
32507db96d56Sopenharmony_ci
32517db96d56Sopenharmony_ci    if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
32527db96d56Sopenharmony_ci        hash = PyObject_Hash(key);
32537db96d56Sopenharmony_ci        if (hash == -1)
32547db96d56Sopenharmony_ci            return NULL;
32557db96d56Sopenharmony_ci    }
32567db96d56Sopenharmony_ci    ix = _Py_dict_lookup(mp, key, hash, &value);
32577db96d56Sopenharmony_ci    if (ix == DKIX_ERROR)
32587db96d56Sopenharmony_ci        return NULL;
32597db96d56Sopenharmony_ci    if (ix == DKIX_EMPTY || value == NULL)
32607db96d56Sopenharmony_ci        Py_RETURN_FALSE;
32617db96d56Sopenharmony_ci    Py_RETURN_TRUE;
32627db96d56Sopenharmony_ci}
32637db96d56Sopenharmony_ci
32647db96d56Sopenharmony_ci/*[clinic input]
32657db96d56Sopenharmony_cidict.get
32667db96d56Sopenharmony_ci
32677db96d56Sopenharmony_ci    key: object
32687db96d56Sopenharmony_ci    default: object = None
32697db96d56Sopenharmony_ci    /
32707db96d56Sopenharmony_ci
32717db96d56Sopenharmony_ciReturn the value for key if key is in the dictionary, else default.
32727db96d56Sopenharmony_ci[clinic start generated code]*/
32737db96d56Sopenharmony_ci
32747db96d56Sopenharmony_cistatic PyObject *
32757db96d56Sopenharmony_cidict_get_impl(PyDictObject *self, PyObject *key, PyObject *default_value)
32767db96d56Sopenharmony_ci/*[clinic end generated code: output=bba707729dee05bf input=279ddb5790b6b107]*/
32777db96d56Sopenharmony_ci{
32787db96d56Sopenharmony_ci    PyObject *val = NULL;
32797db96d56Sopenharmony_ci    Py_hash_t hash;
32807db96d56Sopenharmony_ci    Py_ssize_t ix;
32817db96d56Sopenharmony_ci
32827db96d56Sopenharmony_ci    if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
32837db96d56Sopenharmony_ci        hash = PyObject_Hash(key);
32847db96d56Sopenharmony_ci        if (hash == -1)
32857db96d56Sopenharmony_ci            return NULL;
32867db96d56Sopenharmony_ci    }
32877db96d56Sopenharmony_ci    ix = _Py_dict_lookup(self, key, hash, &val);
32887db96d56Sopenharmony_ci    if (ix == DKIX_ERROR)
32897db96d56Sopenharmony_ci        return NULL;
32907db96d56Sopenharmony_ci    if (ix == DKIX_EMPTY || val == NULL) {
32917db96d56Sopenharmony_ci        val = default_value;
32927db96d56Sopenharmony_ci    }
32937db96d56Sopenharmony_ci    Py_INCREF(val);
32947db96d56Sopenharmony_ci    return val;
32957db96d56Sopenharmony_ci}
32967db96d56Sopenharmony_ci
32977db96d56Sopenharmony_ciPyObject *
32987db96d56Sopenharmony_ciPyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
32997db96d56Sopenharmony_ci{
33007db96d56Sopenharmony_ci    PyDictObject *mp = (PyDictObject *)d;
33017db96d56Sopenharmony_ci    PyObject *value;
33027db96d56Sopenharmony_ci    Py_hash_t hash;
33037db96d56Sopenharmony_ci
33047db96d56Sopenharmony_ci    if (!PyDict_Check(d)) {
33057db96d56Sopenharmony_ci        PyErr_BadInternalCall();
33067db96d56Sopenharmony_ci        return NULL;
33077db96d56Sopenharmony_ci    }
33087db96d56Sopenharmony_ci
33097db96d56Sopenharmony_ci    if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
33107db96d56Sopenharmony_ci        hash = PyObject_Hash(key);
33117db96d56Sopenharmony_ci        if (hash == -1)
33127db96d56Sopenharmony_ci            return NULL;
33137db96d56Sopenharmony_ci    }
33147db96d56Sopenharmony_ci
33157db96d56Sopenharmony_ci    if (mp->ma_keys == Py_EMPTY_KEYS) {
33167db96d56Sopenharmony_ci        Py_INCREF(key);
33177db96d56Sopenharmony_ci        Py_INCREF(defaultobj);
33187db96d56Sopenharmony_ci        if (insert_to_emptydict(mp, key, hash, defaultobj) < 0) {
33197db96d56Sopenharmony_ci            return NULL;
33207db96d56Sopenharmony_ci        }
33217db96d56Sopenharmony_ci        return defaultobj;
33227db96d56Sopenharmony_ci    }
33237db96d56Sopenharmony_ci
33247db96d56Sopenharmony_ci    if (!PyUnicode_CheckExact(key) && DK_IS_UNICODE(mp->ma_keys)) {
33257db96d56Sopenharmony_ci        if (insertion_resize(mp, 0) < 0) {
33267db96d56Sopenharmony_ci            return NULL;
33277db96d56Sopenharmony_ci        }
33287db96d56Sopenharmony_ci    }
33297db96d56Sopenharmony_ci
33307db96d56Sopenharmony_ci    Py_ssize_t ix = _Py_dict_lookup(mp, key, hash, &value);
33317db96d56Sopenharmony_ci    if (ix == DKIX_ERROR)
33327db96d56Sopenharmony_ci        return NULL;
33337db96d56Sopenharmony_ci
33347db96d56Sopenharmony_ci    if (ix == DKIX_EMPTY) {
33357db96d56Sopenharmony_ci        mp->ma_keys->dk_version = 0;
33367db96d56Sopenharmony_ci        value = defaultobj;
33377db96d56Sopenharmony_ci        if (mp->ma_keys->dk_usable <= 0) {
33387db96d56Sopenharmony_ci            if (insertion_resize(mp, 1) < 0) {
33397db96d56Sopenharmony_ci                return NULL;
33407db96d56Sopenharmony_ci            }
33417db96d56Sopenharmony_ci        }
33427db96d56Sopenharmony_ci        Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash);
33437db96d56Sopenharmony_ci        dictkeys_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
33447db96d56Sopenharmony_ci        if (DK_IS_UNICODE(mp->ma_keys)) {
33457db96d56Sopenharmony_ci            assert(PyUnicode_CheckExact(key));
33467db96d56Sopenharmony_ci            PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(mp->ma_keys)[mp->ma_keys->dk_nentries];
33477db96d56Sopenharmony_ci            ep->me_key = key;
33487db96d56Sopenharmony_ci            if (_PyDict_HasSplitTable(mp)) {
33497db96d56Sopenharmony_ci                Py_ssize_t index = (int)mp->ma_keys->dk_nentries;
33507db96d56Sopenharmony_ci                assert(index < SHARED_KEYS_MAX_SIZE);
33517db96d56Sopenharmony_ci                assert(mp->ma_values->values[index] == NULL);
33527db96d56Sopenharmony_ci                mp->ma_values->values[index] = value;
33537db96d56Sopenharmony_ci                _PyDictValues_AddToInsertionOrder(mp->ma_values, index);
33547db96d56Sopenharmony_ci            }
33557db96d56Sopenharmony_ci            else {
33567db96d56Sopenharmony_ci                ep->me_value = value;
33577db96d56Sopenharmony_ci            }
33587db96d56Sopenharmony_ci        }
33597db96d56Sopenharmony_ci        else {
33607db96d56Sopenharmony_ci            PyDictKeyEntry *ep = &DK_ENTRIES(mp->ma_keys)[mp->ma_keys->dk_nentries];
33617db96d56Sopenharmony_ci            ep->me_key = key;
33627db96d56Sopenharmony_ci            ep->me_hash = hash;
33637db96d56Sopenharmony_ci            ep->me_value = value;
33647db96d56Sopenharmony_ci        }
33657db96d56Sopenharmony_ci        Py_INCREF(key);
33667db96d56Sopenharmony_ci        Py_INCREF(value);
33677db96d56Sopenharmony_ci        MAINTAIN_TRACKING(mp, key, value);
33687db96d56Sopenharmony_ci        mp->ma_used++;
33697db96d56Sopenharmony_ci        mp->ma_version_tag = DICT_NEXT_VERSION();
33707db96d56Sopenharmony_ci        mp->ma_keys->dk_usable--;
33717db96d56Sopenharmony_ci        mp->ma_keys->dk_nentries++;
33727db96d56Sopenharmony_ci        assert(mp->ma_keys->dk_usable >= 0);
33737db96d56Sopenharmony_ci    }
33747db96d56Sopenharmony_ci    else if (value == NULL) {
33757db96d56Sopenharmony_ci        value = defaultobj;
33767db96d56Sopenharmony_ci        assert(_PyDict_HasSplitTable(mp));
33777db96d56Sopenharmony_ci        assert(mp->ma_values->values[ix] == NULL);
33787db96d56Sopenharmony_ci        Py_INCREF(value);
33797db96d56Sopenharmony_ci        MAINTAIN_TRACKING(mp, key, value);
33807db96d56Sopenharmony_ci        mp->ma_values->values[ix] = value;
33817db96d56Sopenharmony_ci        _PyDictValues_AddToInsertionOrder(mp->ma_values, ix);
33827db96d56Sopenharmony_ci        mp->ma_used++;
33837db96d56Sopenharmony_ci        mp->ma_version_tag = DICT_NEXT_VERSION();
33847db96d56Sopenharmony_ci    }
33857db96d56Sopenharmony_ci
33867db96d56Sopenharmony_ci    ASSERT_CONSISTENT(mp);
33877db96d56Sopenharmony_ci    return value;
33887db96d56Sopenharmony_ci}
33897db96d56Sopenharmony_ci
33907db96d56Sopenharmony_ci/*[clinic input]
33917db96d56Sopenharmony_cidict.setdefault
33927db96d56Sopenharmony_ci
33937db96d56Sopenharmony_ci    key: object
33947db96d56Sopenharmony_ci    default: object = None
33957db96d56Sopenharmony_ci    /
33967db96d56Sopenharmony_ci
33977db96d56Sopenharmony_ciInsert key with a value of default if key is not in the dictionary.
33987db96d56Sopenharmony_ci
33997db96d56Sopenharmony_ciReturn the value for key if key is in the dictionary, else default.
34007db96d56Sopenharmony_ci[clinic start generated code]*/
34017db96d56Sopenharmony_ci
34027db96d56Sopenharmony_cistatic PyObject *
34037db96d56Sopenharmony_cidict_setdefault_impl(PyDictObject *self, PyObject *key,
34047db96d56Sopenharmony_ci                     PyObject *default_value)
34057db96d56Sopenharmony_ci/*[clinic end generated code: output=f8c1101ebf69e220 input=0f063756e815fd9d]*/
34067db96d56Sopenharmony_ci{
34077db96d56Sopenharmony_ci    PyObject *val;
34087db96d56Sopenharmony_ci
34097db96d56Sopenharmony_ci    val = PyDict_SetDefault((PyObject *)self, key, default_value);
34107db96d56Sopenharmony_ci    Py_XINCREF(val);
34117db96d56Sopenharmony_ci    return val;
34127db96d56Sopenharmony_ci}
34137db96d56Sopenharmony_ci
34147db96d56Sopenharmony_cistatic PyObject *
34157db96d56Sopenharmony_cidict_clear(PyDictObject *mp, PyObject *Py_UNUSED(ignored))
34167db96d56Sopenharmony_ci{
34177db96d56Sopenharmony_ci    PyDict_Clear((PyObject *)mp);
34187db96d56Sopenharmony_ci    Py_RETURN_NONE;
34197db96d56Sopenharmony_ci}
34207db96d56Sopenharmony_ci
34217db96d56Sopenharmony_ci/*[clinic input]
34227db96d56Sopenharmony_cidict.pop
34237db96d56Sopenharmony_ci
34247db96d56Sopenharmony_ci    key: object
34257db96d56Sopenharmony_ci    default: object = NULL
34267db96d56Sopenharmony_ci    /
34277db96d56Sopenharmony_ci
34287db96d56Sopenharmony_ciD.pop(k[,d]) -> v, remove specified key and return the corresponding value.
34297db96d56Sopenharmony_ci
34307db96d56Sopenharmony_ciIf the key is not found, return the default if given; otherwise,
34317db96d56Sopenharmony_ciraise a KeyError.
34327db96d56Sopenharmony_ci[clinic start generated code]*/
34337db96d56Sopenharmony_ci
34347db96d56Sopenharmony_cistatic PyObject *
34357db96d56Sopenharmony_cidict_pop_impl(PyDictObject *self, PyObject *key, PyObject *default_value)
34367db96d56Sopenharmony_ci/*[clinic end generated code: output=3abb47b89f24c21c input=e221baa01044c44c]*/
34377db96d56Sopenharmony_ci{
34387db96d56Sopenharmony_ci    return _PyDict_Pop((PyObject*)self, key, default_value);
34397db96d56Sopenharmony_ci}
34407db96d56Sopenharmony_ci
34417db96d56Sopenharmony_ci/*[clinic input]
34427db96d56Sopenharmony_cidict.popitem
34437db96d56Sopenharmony_ci
34447db96d56Sopenharmony_ciRemove and return a (key, value) pair as a 2-tuple.
34457db96d56Sopenharmony_ci
34467db96d56Sopenharmony_ciPairs are returned in LIFO (last-in, first-out) order.
34477db96d56Sopenharmony_ciRaises KeyError if the dict is empty.
34487db96d56Sopenharmony_ci[clinic start generated code]*/
34497db96d56Sopenharmony_ci
34507db96d56Sopenharmony_cistatic PyObject *
34517db96d56Sopenharmony_cidict_popitem_impl(PyDictObject *self)
34527db96d56Sopenharmony_ci/*[clinic end generated code: output=e65fcb04420d230d input=1c38a49f21f64941]*/
34537db96d56Sopenharmony_ci{
34547db96d56Sopenharmony_ci    Py_ssize_t i, j;
34557db96d56Sopenharmony_ci    PyObject *res;
34567db96d56Sopenharmony_ci
34577db96d56Sopenharmony_ci    /* Allocate the result tuple before checking the size.  Believe it
34587db96d56Sopenharmony_ci     * or not, this allocation could trigger a garbage collection which
34597db96d56Sopenharmony_ci     * could empty the dict, so if we checked the size first and that
34607db96d56Sopenharmony_ci     * happened, the result would be an infinite loop (searching for an
34617db96d56Sopenharmony_ci     * entry that no longer exists).  Note that the usual popitem()
34627db96d56Sopenharmony_ci     * idiom is "while d: k, v = d.popitem()". so needing to throw the
34637db96d56Sopenharmony_ci     * tuple away if the dict *is* empty isn't a significant
34647db96d56Sopenharmony_ci     * inefficiency -- possible, but unlikely in practice.
34657db96d56Sopenharmony_ci     */
34667db96d56Sopenharmony_ci    res = PyTuple_New(2);
34677db96d56Sopenharmony_ci    if (res == NULL)
34687db96d56Sopenharmony_ci        return NULL;
34697db96d56Sopenharmony_ci    if (self->ma_used == 0) {
34707db96d56Sopenharmony_ci        Py_DECREF(res);
34717db96d56Sopenharmony_ci        PyErr_SetString(PyExc_KeyError, "popitem(): dictionary is empty");
34727db96d56Sopenharmony_ci        return NULL;
34737db96d56Sopenharmony_ci    }
34747db96d56Sopenharmony_ci    /* Convert split table to combined table */
34757db96d56Sopenharmony_ci    if (self->ma_keys->dk_kind == DICT_KEYS_SPLIT) {
34767db96d56Sopenharmony_ci        if (dictresize(self, DK_LOG_SIZE(self->ma_keys), 1)) {
34777db96d56Sopenharmony_ci            Py_DECREF(res);
34787db96d56Sopenharmony_ci            return NULL;
34797db96d56Sopenharmony_ci        }
34807db96d56Sopenharmony_ci    }
34817db96d56Sopenharmony_ci    self->ma_keys->dk_version = 0;
34827db96d56Sopenharmony_ci
34837db96d56Sopenharmony_ci    /* Pop last item */
34847db96d56Sopenharmony_ci    PyObject *key, *value;
34857db96d56Sopenharmony_ci    Py_hash_t hash;
34867db96d56Sopenharmony_ci    if (DK_IS_UNICODE(self->ma_keys)) {
34877db96d56Sopenharmony_ci        PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(self->ma_keys);
34887db96d56Sopenharmony_ci        i = self->ma_keys->dk_nentries - 1;
34897db96d56Sopenharmony_ci        while (i >= 0 && ep0[i].me_value == NULL) {
34907db96d56Sopenharmony_ci            i--;
34917db96d56Sopenharmony_ci        }
34927db96d56Sopenharmony_ci        assert(i >= 0);
34937db96d56Sopenharmony_ci
34947db96d56Sopenharmony_ci        key = ep0[i].me_key;
34957db96d56Sopenharmony_ci        hash = unicode_get_hash(key);
34967db96d56Sopenharmony_ci        value = ep0[i].me_value;
34977db96d56Sopenharmony_ci        ep0[i].me_key = NULL;
34987db96d56Sopenharmony_ci        ep0[i].me_value = NULL;
34997db96d56Sopenharmony_ci    }
35007db96d56Sopenharmony_ci    else {
35017db96d56Sopenharmony_ci        PyDictKeyEntry *ep0 = DK_ENTRIES(self->ma_keys);
35027db96d56Sopenharmony_ci        i = self->ma_keys->dk_nentries - 1;
35037db96d56Sopenharmony_ci        while (i >= 0 && ep0[i].me_value == NULL) {
35047db96d56Sopenharmony_ci            i--;
35057db96d56Sopenharmony_ci        }
35067db96d56Sopenharmony_ci        assert(i >= 0);
35077db96d56Sopenharmony_ci
35087db96d56Sopenharmony_ci        key = ep0[i].me_key;
35097db96d56Sopenharmony_ci        hash = ep0[i].me_hash;
35107db96d56Sopenharmony_ci        value = ep0[i].me_value;
35117db96d56Sopenharmony_ci        ep0[i].me_key = NULL;
35127db96d56Sopenharmony_ci        ep0[i].me_hash = -1;
35137db96d56Sopenharmony_ci        ep0[i].me_value = NULL;
35147db96d56Sopenharmony_ci    }
35157db96d56Sopenharmony_ci
35167db96d56Sopenharmony_ci    j = lookdict_index(self->ma_keys, hash, i);
35177db96d56Sopenharmony_ci    assert(j >= 0);
35187db96d56Sopenharmony_ci    assert(dictkeys_get_index(self->ma_keys, j) == i);
35197db96d56Sopenharmony_ci    dictkeys_set_index(self->ma_keys, j, DKIX_DUMMY);
35207db96d56Sopenharmony_ci
35217db96d56Sopenharmony_ci    PyTuple_SET_ITEM(res, 0, key);
35227db96d56Sopenharmony_ci    PyTuple_SET_ITEM(res, 1, value);
35237db96d56Sopenharmony_ci    /* We can't dk_usable++ since there is DKIX_DUMMY in indices */
35247db96d56Sopenharmony_ci    self->ma_keys->dk_nentries = i;
35257db96d56Sopenharmony_ci    self->ma_used--;
35267db96d56Sopenharmony_ci    self->ma_version_tag = DICT_NEXT_VERSION();
35277db96d56Sopenharmony_ci    ASSERT_CONSISTENT(self);
35287db96d56Sopenharmony_ci    return res;
35297db96d56Sopenharmony_ci}
35307db96d56Sopenharmony_ci
35317db96d56Sopenharmony_cistatic int
35327db96d56Sopenharmony_cidict_traverse(PyObject *op, visitproc visit, void *arg)
35337db96d56Sopenharmony_ci{
35347db96d56Sopenharmony_ci    PyDictObject *mp = (PyDictObject *)op;
35357db96d56Sopenharmony_ci    PyDictKeysObject *keys = mp->ma_keys;
35367db96d56Sopenharmony_ci    Py_ssize_t i, n = keys->dk_nentries;
35377db96d56Sopenharmony_ci
35387db96d56Sopenharmony_ci    if (DK_IS_UNICODE(keys)) {
35397db96d56Sopenharmony_ci        if (mp->ma_values != NULL) {
35407db96d56Sopenharmony_ci            for (i = 0; i < n; i++) {
35417db96d56Sopenharmony_ci                Py_VISIT(mp->ma_values->values[i]);
35427db96d56Sopenharmony_ci            }
35437db96d56Sopenharmony_ci        }
35447db96d56Sopenharmony_ci        else {
35457db96d56Sopenharmony_ci            PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys);
35467db96d56Sopenharmony_ci            for (i = 0; i < n; i++) {
35477db96d56Sopenharmony_ci                Py_VISIT(entries[i].me_value);
35487db96d56Sopenharmony_ci            }
35497db96d56Sopenharmony_ci        }
35507db96d56Sopenharmony_ci    }
35517db96d56Sopenharmony_ci    else {
35527db96d56Sopenharmony_ci        PyDictKeyEntry *entries = DK_ENTRIES(keys);
35537db96d56Sopenharmony_ci        for (i = 0; i < n; i++) {
35547db96d56Sopenharmony_ci            if (entries[i].me_value != NULL) {
35557db96d56Sopenharmony_ci                Py_VISIT(entries[i].me_value);
35567db96d56Sopenharmony_ci                Py_VISIT(entries[i].me_key);
35577db96d56Sopenharmony_ci            }
35587db96d56Sopenharmony_ci        }
35597db96d56Sopenharmony_ci    }
35607db96d56Sopenharmony_ci    return 0;
35617db96d56Sopenharmony_ci}
35627db96d56Sopenharmony_ci
35637db96d56Sopenharmony_cistatic int
35647db96d56Sopenharmony_cidict_tp_clear(PyObject *op)
35657db96d56Sopenharmony_ci{
35667db96d56Sopenharmony_ci    PyDict_Clear(op);
35677db96d56Sopenharmony_ci    return 0;
35687db96d56Sopenharmony_ci}
35697db96d56Sopenharmony_ci
35707db96d56Sopenharmony_cistatic PyObject *dictiter_new(PyDictObject *, PyTypeObject *);
35717db96d56Sopenharmony_ci
35727db96d56Sopenharmony_ciPy_ssize_t
35737db96d56Sopenharmony_ci_PyDict_SizeOf(PyDictObject *mp)
35747db96d56Sopenharmony_ci{
35757db96d56Sopenharmony_ci    Py_ssize_t res;
35767db96d56Sopenharmony_ci
35777db96d56Sopenharmony_ci    res = _PyObject_SIZE(Py_TYPE(mp));
35787db96d56Sopenharmony_ci    if (mp->ma_values) {
35797db96d56Sopenharmony_ci        res += shared_keys_usable_size(mp->ma_keys) * sizeof(PyObject*);
35807db96d56Sopenharmony_ci    }
35817db96d56Sopenharmony_ci    /* If the dictionary is split, the keys portion is accounted-for
35827db96d56Sopenharmony_ci       in the type object. */
35837db96d56Sopenharmony_ci    if (mp->ma_keys->dk_refcnt == 1) {
35847db96d56Sopenharmony_ci        res += _PyDict_KeysSize(mp->ma_keys);
35857db96d56Sopenharmony_ci    }
35867db96d56Sopenharmony_ci    return res;
35877db96d56Sopenharmony_ci}
35887db96d56Sopenharmony_ci
35897db96d56Sopenharmony_ciPy_ssize_t
35907db96d56Sopenharmony_ci_PyDict_KeysSize(PyDictKeysObject *keys)
35917db96d56Sopenharmony_ci{
35927db96d56Sopenharmony_ci    size_t es = keys->dk_kind == DICT_KEYS_GENERAL
35937db96d56Sopenharmony_ci        ?  sizeof(PyDictKeyEntry) : sizeof(PyDictUnicodeEntry);
35947db96d56Sopenharmony_ci    return (sizeof(PyDictKeysObject)
35957db96d56Sopenharmony_ci            + ((size_t)1 << keys->dk_log2_index_bytes)
35967db96d56Sopenharmony_ci            + USABLE_FRACTION(DK_SIZE(keys)) * es);
35977db96d56Sopenharmony_ci}
35987db96d56Sopenharmony_ci
35997db96d56Sopenharmony_cistatic PyObject *
36007db96d56Sopenharmony_cidict_sizeof(PyDictObject *mp, PyObject *Py_UNUSED(ignored))
36017db96d56Sopenharmony_ci{
36027db96d56Sopenharmony_ci    return PyLong_FromSsize_t(_PyDict_SizeOf(mp));
36037db96d56Sopenharmony_ci}
36047db96d56Sopenharmony_ci
36057db96d56Sopenharmony_cistatic PyObject *
36067db96d56Sopenharmony_cidict_or(PyObject *self, PyObject *other)
36077db96d56Sopenharmony_ci{
36087db96d56Sopenharmony_ci    if (!PyDict_Check(self) || !PyDict_Check(other)) {
36097db96d56Sopenharmony_ci        Py_RETURN_NOTIMPLEMENTED;
36107db96d56Sopenharmony_ci    }
36117db96d56Sopenharmony_ci    PyObject *new = PyDict_Copy(self);
36127db96d56Sopenharmony_ci    if (new == NULL) {
36137db96d56Sopenharmony_ci        return NULL;
36147db96d56Sopenharmony_ci    }
36157db96d56Sopenharmony_ci    if (dict_update_arg(new, other)) {
36167db96d56Sopenharmony_ci        Py_DECREF(new);
36177db96d56Sopenharmony_ci        return NULL;
36187db96d56Sopenharmony_ci    }
36197db96d56Sopenharmony_ci    return new;
36207db96d56Sopenharmony_ci}
36217db96d56Sopenharmony_ci
36227db96d56Sopenharmony_cistatic PyObject *
36237db96d56Sopenharmony_cidict_ior(PyObject *self, PyObject *other)
36247db96d56Sopenharmony_ci{
36257db96d56Sopenharmony_ci    if (dict_update_arg(self, other)) {
36267db96d56Sopenharmony_ci        return NULL;
36277db96d56Sopenharmony_ci    }
36287db96d56Sopenharmony_ci    Py_INCREF(self);
36297db96d56Sopenharmony_ci    return self;
36307db96d56Sopenharmony_ci}
36317db96d56Sopenharmony_ci
36327db96d56Sopenharmony_ciPyDoc_STRVAR(getitem__doc__, "x.__getitem__(y) <==> x[y]");
36337db96d56Sopenharmony_ci
36347db96d56Sopenharmony_ciPyDoc_STRVAR(sizeof__doc__,
36357db96d56Sopenharmony_ci"D.__sizeof__() -> size of D in memory, in bytes");
36367db96d56Sopenharmony_ci
36377db96d56Sopenharmony_ciPyDoc_STRVAR(update__doc__,
36387db96d56Sopenharmony_ci"D.update([E, ]**F) -> None.  Update D from dict/iterable E and F.\n\
36397db96d56Sopenharmony_ciIf E is present and has a .keys() method, then does:  for k in E: D[k] = E[k]\n\
36407db96d56Sopenharmony_ciIf E is present and lacks a .keys() method, then does:  for k, v in E: D[k] = v\n\
36417db96d56Sopenharmony_ciIn either case, this is followed by: for k in F:  D[k] = F[k]");
36427db96d56Sopenharmony_ci
36437db96d56Sopenharmony_ciPyDoc_STRVAR(clear__doc__,
36447db96d56Sopenharmony_ci"D.clear() -> None.  Remove all items from D.");
36457db96d56Sopenharmony_ci
36467db96d56Sopenharmony_ciPyDoc_STRVAR(copy__doc__,
36477db96d56Sopenharmony_ci"D.copy() -> a shallow copy of D");
36487db96d56Sopenharmony_ci
36497db96d56Sopenharmony_ci/* Forward */
36507db96d56Sopenharmony_cistatic PyObject *dictkeys_new(PyObject *, PyObject *);
36517db96d56Sopenharmony_cistatic PyObject *dictitems_new(PyObject *, PyObject *);
36527db96d56Sopenharmony_cistatic PyObject *dictvalues_new(PyObject *, PyObject *);
36537db96d56Sopenharmony_ci
36547db96d56Sopenharmony_ciPyDoc_STRVAR(keys__doc__,
36557db96d56Sopenharmony_ci             "D.keys() -> a set-like object providing a view on D's keys");
36567db96d56Sopenharmony_ciPyDoc_STRVAR(items__doc__,
36577db96d56Sopenharmony_ci             "D.items() -> a set-like object providing a view on D's items");
36587db96d56Sopenharmony_ciPyDoc_STRVAR(values__doc__,
36597db96d56Sopenharmony_ci             "D.values() -> an object providing a view on D's values");
36607db96d56Sopenharmony_ci
36617db96d56Sopenharmony_cistatic PyMethodDef mapp_methods[] = {
36627db96d56Sopenharmony_ci    DICT___CONTAINS___METHODDEF
36637db96d56Sopenharmony_ci    {"__getitem__", _PyCFunction_CAST(dict_subscript),        METH_O | METH_COEXIST,
36647db96d56Sopenharmony_ci     getitem__doc__},
36657db96d56Sopenharmony_ci    {"__sizeof__",      _PyCFunction_CAST(dict_sizeof),       METH_NOARGS,
36667db96d56Sopenharmony_ci     sizeof__doc__},
36677db96d56Sopenharmony_ci    DICT_GET_METHODDEF
36687db96d56Sopenharmony_ci    DICT_SETDEFAULT_METHODDEF
36697db96d56Sopenharmony_ci    DICT_POP_METHODDEF
36707db96d56Sopenharmony_ci    DICT_POPITEM_METHODDEF
36717db96d56Sopenharmony_ci    {"keys",            dictkeys_new,                   METH_NOARGS,
36727db96d56Sopenharmony_ci    keys__doc__},
36737db96d56Sopenharmony_ci    {"items",           dictitems_new,                  METH_NOARGS,
36747db96d56Sopenharmony_ci    items__doc__},
36757db96d56Sopenharmony_ci    {"values",          dictvalues_new,                 METH_NOARGS,
36767db96d56Sopenharmony_ci    values__doc__},
36777db96d56Sopenharmony_ci    {"update",          _PyCFunction_CAST(dict_update), METH_VARARGS | METH_KEYWORDS,
36787db96d56Sopenharmony_ci     update__doc__},
36797db96d56Sopenharmony_ci    DICT_FROMKEYS_METHODDEF
36807db96d56Sopenharmony_ci    {"clear",           (PyCFunction)dict_clear,        METH_NOARGS,
36817db96d56Sopenharmony_ci     clear__doc__},
36827db96d56Sopenharmony_ci    {"copy",            (PyCFunction)dict_copy,         METH_NOARGS,
36837db96d56Sopenharmony_ci     copy__doc__},
36847db96d56Sopenharmony_ci    DICT___REVERSED___METHODDEF
36857db96d56Sopenharmony_ci    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
36867db96d56Sopenharmony_ci    {NULL,              NULL}   /* sentinel */
36877db96d56Sopenharmony_ci};
36887db96d56Sopenharmony_ci
36897db96d56Sopenharmony_ci/* Return 1 if `key` is in dict `op`, 0 if not, and -1 on error. */
36907db96d56Sopenharmony_ciint
36917db96d56Sopenharmony_ciPyDict_Contains(PyObject *op, PyObject *key)
36927db96d56Sopenharmony_ci{
36937db96d56Sopenharmony_ci    Py_hash_t hash;
36947db96d56Sopenharmony_ci    Py_ssize_t ix;
36957db96d56Sopenharmony_ci    PyDictObject *mp = (PyDictObject *)op;
36967db96d56Sopenharmony_ci    PyObject *value;
36977db96d56Sopenharmony_ci
36987db96d56Sopenharmony_ci    if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
36997db96d56Sopenharmony_ci        hash = PyObject_Hash(key);
37007db96d56Sopenharmony_ci        if (hash == -1)
37017db96d56Sopenharmony_ci            return -1;
37027db96d56Sopenharmony_ci    }
37037db96d56Sopenharmony_ci    ix = _Py_dict_lookup(mp, key, hash, &value);
37047db96d56Sopenharmony_ci    if (ix == DKIX_ERROR)
37057db96d56Sopenharmony_ci        return -1;
37067db96d56Sopenharmony_ci    return (ix != DKIX_EMPTY && value != NULL);
37077db96d56Sopenharmony_ci}
37087db96d56Sopenharmony_ci
37097db96d56Sopenharmony_ci/* Internal version of PyDict_Contains used when the hash value is already known */
37107db96d56Sopenharmony_ciint
37117db96d56Sopenharmony_ci_PyDict_Contains_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
37127db96d56Sopenharmony_ci{
37137db96d56Sopenharmony_ci    PyDictObject *mp = (PyDictObject *)op;
37147db96d56Sopenharmony_ci    PyObject *value;
37157db96d56Sopenharmony_ci    Py_ssize_t ix;
37167db96d56Sopenharmony_ci
37177db96d56Sopenharmony_ci    ix = _Py_dict_lookup(mp, key, hash, &value);
37187db96d56Sopenharmony_ci    if (ix == DKIX_ERROR)
37197db96d56Sopenharmony_ci        return -1;
37207db96d56Sopenharmony_ci    return (ix != DKIX_EMPTY && value != NULL);
37217db96d56Sopenharmony_ci}
37227db96d56Sopenharmony_ci
37237db96d56Sopenharmony_ciint
37247db96d56Sopenharmony_ci_PyDict_ContainsId(PyObject *op, _Py_Identifier *key)
37257db96d56Sopenharmony_ci{
37267db96d56Sopenharmony_ci    PyObject *kv = _PyUnicode_FromId(key); /* borrowed */
37277db96d56Sopenharmony_ci    if (kv == NULL) {
37287db96d56Sopenharmony_ci        return -1;
37297db96d56Sopenharmony_ci    }
37307db96d56Sopenharmony_ci    return PyDict_Contains(op, kv);
37317db96d56Sopenharmony_ci}
37327db96d56Sopenharmony_ci
37337db96d56Sopenharmony_ci/* Hack to implement "key in dict" */
37347db96d56Sopenharmony_cistatic PySequenceMethods dict_as_sequence = {
37357db96d56Sopenharmony_ci    0,                          /* sq_length */
37367db96d56Sopenharmony_ci    0,                          /* sq_concat */
37377db96d56Sopenharmony_ci    0,                          /* sq_repeat */
37387db96d56Sopenharmony_ci    0,                          /* sq_item */
37397db96d56Sopenharmony_ci    0,                          /* sq_slice */
37407db96d56Sopenharmony_ci    0,                          /* sq_ass_item */
37417db96d56Sopenharmony_ci    0,                          /* sq_ass_slice */
37427db96d56Sopenharmony_ci    PyDict_Contains,            /* sq_contains */
37437db96d56Sopenharmony_ci    0,                          /* sq_inplace_concat */
37447db96d56Sopenharmony_ci    0,                          /* sq_inplace_repeat */
37457db96d56Sopenharmony_ci};
37467db96d56Sopenharmony_ci
37477db96d56Sopenharmony_cistatic PyNumberMethods dict_as_number = {
37487db96d56Sopenharmony_ci    .nb_or = dict_or,
37497db96d56Sopenharmony_ci    .nb_inplace_or = dict_ior,
37507db96d56Sopenharmony_ci};
37517db96d56Sopenharmony_ci
37527db96d56Sopenharmony_cistatic PyObject *
37537db96d56Sopenharmony_cidict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
37547db96d56Sopenharmony_ci{
37557db96d56Sopenharmony_ci    assert(type != NULL);
37567db96d56Sopenharmony_ci    assert(type->tp_alloc != NULL);
37577db96d56Sopenharmony_ci    // dict subclasses must implement the GC protocol
37587db96d56Sopenharmony_ci    assert(_PyType_IS_GC(type));
37597db96d56Sopenharmony_ci
37607db96d56Sopenharmony_ci    PyObject *self = type->tp_alloc(type, 0);
37617db96d56Sopenharmony_ci    if (self == NULL) {
37627db96d56Sopenharmony_ci        return NULL;
37637db96d56Sopenharmony_ci    }
37647db96d56Sopenharmony_ci    PyDictObject *d = (PyDictObject *)self;
37657db96d56Sopenharmony_ci
37667db96d56Sopenharmony_ci    d->ma_used = 0;
37677db96d56Sopenharmony_ci    d->ma_version_tag = DICT_NEXT_VERSION();
37687db96d56Sopenharmony_ci    dictkeys_incref(Py_EMPTY_KEYS);
37697db96d56Sopenharmony_ci    d->ma_keys = Py_EMPTY_KEYS;
37707db96d56Sopenharmony_ci    d->ma_values = NULL;
37717db96d56Sopenharmony_ci    ASSERT_CONSISTENT(d);
37727db96d56Sopenharmony_ci
37737db96d56Sopenharmony_ci    if (type != &PyDict_Type) {
37747db96d56Sopenharmony_ci        // Don't track if a subclass tp_alloc is PyType_GenericAlloc()
37757db96d56Sopenharmony_ci        if (!_PyObject_GC_IS_TRACKED(d)) {
37767db96d56Sopenharmony_ci            _PyObject_GC_TRACK(d);
37777db96d56Sopenharmony_ci        }
37787db96d56Sopenharmony_ci    }
37797db96d56Sopenharmony_ci    else {
37807db96d56Sopenharmony_ci        // _PyType_AllocNoTrack() does not track the created object
37817db96d56Sopenharmony_ci        assert(!_PyObject_GC_IS_TRACKED(d));
37827db96d56Sopenharmony_ci    }
37837db96d56Sopenharmony_ci    return self;
37847db96d56Sopenharmony_ci}
37857db96d56Sopenharmony_ci
37867db96d56Sopenharmony_cistatic int
37877db96d56Sopenharmony_cidict_init(PyObject *self, PyObject *args, PyObject *kwds)
37887db96d56Sopenharmony_ci{
37897db96d56Sopenharmony_ci    return dict_update_common(self, args, kwds, "dict");
37907db96d56Sopenharmony_ci}
37917db96d56Sopenharmony_ci
37927db96d56Sopenharmony_cistatic PyObject *
37937db96d56Sopenharmony_cidict_vectorcall(PyObject *type, PyObject * const*args,
37947db96d56Sopenharmony_ci                size_t nargsf, PyObject *kwnames)
37957db96d56Sopenharmony_ci{
37967db96d56Sopenharmony_ci    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
37977db96d56Sopenharmony_ci    if (!_PyArg_CheckPositional("dict", nargs, 0, 1)) {
37987db96d56Sopenharmony_ci        return NULL;
37997db96d56Sopenharmony_ci    }
38007db96d56Sopenharmony_ci
38017db96d56Sopenharmony_ci    PyObject *self = dict_new(_PyType_CAST(type), NULL, NULL);
38027db96d56Sopenharmony_ci    if (self == NULL) {
38037db96d56Sopenharmony_ci        return NULL;
38047db96d56Sopenharmony_ci    }
38057db96d56Sopenharmony_ci    if (nargs == 1) {
38067db96d56Sopenharmony_ci        if (dict_update_arg(self, args[0]) < 0) {
38077db96d56Sopenharmony_ci            Py_DECREF(self);
38087db96d56Sopenharmony_ci            return NULL;
38097db96d56Sopenharmony_ci        }
38107db96d56Sopenharmony_ci        args++;
38117db96d56Sopenharmony_ci    }
38127db96d56Sopenharmony_ci    if (kwnames != NULL) {
38137db96d56Sopenharmony_ci        for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(kwnames); i++) {
38147db96d56Sopenharmony_ci            if (PyDict_SetItem(self, PyTuple_GET_ITEM(kwnames, i), args[i]) < 0) {
38157db96d56Sopenharmony_ci                Py_DECREF(self);
38167db96d56Sopenharmony_ci                return NULL;
38177db96d56Sopenharmony_ci            }
38187db96d56Sopenharmony_ci        }
38197db96d56Sopenharmony_ci    }
38207db96d56Sopenharmony_ci    return self;
38217db96d56Sopenharmony_ci}
38227db96d56Sopenharmony_ci
38237db96d56Sopenharmony_cistatic PyObject *
38247db96d56Sopenharmony_cidict_iter(PyDictObject *dict)
38257db96d56Sopenharmony_ci{
38267db96d56Sopenharmony_ci    return dictiter_new(dict, &PyDictIterKey_Type);
38277db96d56Sopenharmony_ci}
38287db96d56Sopenharmony_ci
38297db96d56Sopenharmony_ciPyDoc_STRVAR(dictionary_doc,
38307db96d56Sopenharmony_ci"dict() -> new empty dictionary\n"
38317db96d56Sopenharmony_ci"dict(mapping) -> new dictionary initialized from a mapping object's\n"
38327db96d56Sopenharmony_ci"    (key, value) pairs\n"
38337db96d56Sopenharmony_ci"dict(iterable) -> new dictionary initialized as if via:\n"
38347db96d56Sopenharmony_ci"    d = {}\n"
38357db96d56Sopenharmony_ci"    for k, v in iterable:\n"
38367db96d56Sopenharmony_ci"        d[k] = v\n"
38377db96d56Sopenharmony_ci"dict(**kwargs) -> new dictionary initialized with the name=value pairs\n"
38387db96d56Sopenharmony_ci"    in the keyword argument list.  For example:  dict(one=1, two=2)");
38397db96d56Sopenharmony_ci
38407db96d56Sopenharmony_ciPyTypeObject PyDict_Type = {
38417db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
38427db96d56Sopenharmony_ci    "dict",
38437db96d56Sopenharmony_ci    sizeof(PyDictObject),
38447db96d56Sopenharmony_ci    0,
38457db96d56Sopenharmony_ci    (destructor)dict_dealloc,                   /* tp_dealloc */
38467db96d56Sopenharmony_ci    0,                                          /* tp_vectorcall_offset */
38477db96d56Sopenharmony_ci    0,                                          /* tp_getattr */
38487db96d56Sopenharmony_ci    0,                                          /* tp_setattr */
38497db96d56Sopenharmony_ci    0,                                          /* tp_as_async */
38507db96d56Sopenharmony_ci    (reprfunc)dict_repr,                        /* tp_repr */
38517db96d56Sopenharmony_ci    &dict_as_number,                            /* tp_as_number */
38527db96d56Sopenharmony_ci    &dict_as_sequence,                          /* tp_as_sequence */
38537db96d56Sopenharmony_ci    &dict_as_mapping,                           /* tp_as_mapping */
38547db96d56Sopenharmony_ci    PyObject_HashNotImplemented,                /* tp_hash */
38557db96d56Sopenharmony_ci    0,                                          /* tp_call */
38567db96d56Sopenharmony_ci    0,                                          /* tp_str */
38577db96d56Sopenharmony_ci    PyObject_GenericGetAttr,                    /* tp_getattro */
38587db96d56Sopenharmony_ci    0,                                          /* tp_setattro */
38597db96d56Sopenharmony_ci    0,                                          /* tp_as_buffer */
38607db96d56Sopenharmony_ci    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
38617db96d56Sopenharmony_ci        Py_TPFLAGS_BASETYPE | Py_TPFLAGS_DICT_SUBCLASS |
38627db96d56Sopenharmony_ci        _Py_TPFLAGS_MATCH_SELF | Py_TPFLAGS_MAPPING,  /* tp_flags */
38637db96d56Sopenharmony_ci    dictionary_doc,                             /* tp_doc */
38647db96d56Sopenharmony_ci    dict_traverse,                              /* tp_traverse */
38657db96d56Sopenharmony_ci    dict_tp_clear,                              /* tp_clear */
38667db96d56Sopenharmony_ci    dict_richcompare,                           /* tp_richcompare */
38677db96d56Sopenharmony_ci    0,                                          /* tp_weaklistoffset */
38687db96d56Sopenharmony_ci    (getiterfunc)dict_iter,                     /* tp_iter */
38697db96d56Sopenharmony_ci    0,                                          /* tp_iternext */
38707db96d56Sopenharmony_ci    mapp_methods,                               /* tp_methods */
38717db96d56Sopenharmony_ci    0,                                          /* tp_members */
38727db96d56Sopenharmony_ci    0,                                          /* tp_getset */
38737db96d56Sopenharmony_ci    0,                                          /* tp_base */
38747db96d56Sopenharmony_ci    0,                                          /* tp_dict */
38757db96d56Sopenharmony_ci    0,                                          /* tp_descr_get */
38767db96d56Sopenharmony_ci    0,                                          /* tp_descr_set */
38777db96d56Sopenharmony_ci    0,                                          /* tp_dictoffset */
38787db96d56Sopenharmony_ci    dict_init,                                  /* tp_init */
38797db96d56Sopenharmony_ci    _PyType_AllocNoTrack,                       /* tp_alloc */
38807db96d56Sopenharmony_ci    dict_new,                                   /* tp_new */
38817db96d56Sopenharmony_ci    PyObject_GC_Del,                            /* tp_free */
38827db96d56Sopenharmony_ci    .tp_vectorcall = dict_vectorcall,
38837db96d56Sopenharmony_ci};
38847db96d56Sopenharmony_ci
38857db96d56Sopenharmony_ci/* For backward compatibility with old dictionary interface */
38867db96d56Sopenharmony_ci
38877db96d56Sopenharmony_ciPyObject *
38887db96d56Sopenharmony_ciPyDict_GetItemString(PyObject *v, const char *key)
38897db96d56Sopenharmony_ci{
38907db96d56Sopenharmony_ci    PyObject *kv, *rv;
38917db96d56Sopenharmony_ci    kv = PyUnicode_FromString(key);
38927db96d56Sopenharmony_ci    if (kv == NULL) {
38937db96d56Sopenharmony_ci        PyErr_Clear();
38947db96d56Sopenharmony_ci        return NULL;
38957db96d56Sopenharmony_ci    }
38967db96d56Sopenharmony_ci    rv = PyDict_GetItem(v, kv);
38977db96d56Sopenharmony_ci    Py_DECREF(kv);
38987db96d56Sopenharmony_ci    return rv;
38997db96d56Sopenharmony_ci}
39007db96d56Sopenharmony_ci
39017db96d56Sopenharmony_ciint
39027db96d56Sopenharmony_ci_PyDict_SetItemId(PyObject *v, _Py_Identifier *key, PyObject *item)
39037db96d56Sopenharmony_ci{
39047db96d56Sopenharmony_ci    PyObject *kv;
39057db96d56Sopenharmony_ci    kv = _PyUnicode_FromId(key); /* borrowed */
39067db96d56Sopenharmony_ci    if (kv == NULL)
39077db96d56Sopenharmony_ci        return -1;
39087db96d56Sopenharmony_ci    return PyDict_SetItem(v, kv, item);
39097db96d56Sopenharmony_ci}
39107db96d56Sopenharmony_ci
39117db96d56Sopenharmony_ciint
39127db96d56Sopenharmony_ciPyDict_SetItemString(PyObject *v, const char *key, PyObject *item)
39137db96d56Sopenharmony_ci{
39147db96d56Sopenharmony_ci    PyObject *kv;
39157db96d56Sopenharmony_ci    int err;
39167db96d56Sopenharmony_ci    kv = PyUnicode_FromString(key);
39177db96d56Sopenharmony_ci    if (kv == NULL)
39187db96d56Sopenharmony_ci        return -1;
39197db96d56Sopenharmony_ci    PyUnicode_InternInPlace(&kv); /* XXX Should we really? */
39207db96d56Sopenharmony_ci    err = PyDict_SetItem(v, kv, item);
39217db96d56Sopenharmony_ci    Py_DECREF(kv);
39227db96d56Sopenharmony_ci    return err;
39237db96d56Sopenharmony_ci}
39247db96d56Sopenharmony_ci
39257db96d56Sopenharmony_ciint
39267db96d56Sopenharmony_ci_PyDict_DelItemId(PyObject *v, _Py_Identifier *key)
39277db96d56Sopenharmony_ci{
39287db96d56Sopenharmony_ci    PyObject *kv = _PyUnicode_FromId(key); /* borrowed */
39297db96d56Sopenharmony_ci    if (kv == NULL)
39307db96d56Sopenharmony_ci        return -1;
39317db96d56Sopenharmony_ci    return PyDict_DelItem(v, kv);
39327db96d56Sopenharmony_ci}
39337db96d56Sopenharmony_ci
39347db96d56Sopenharmony_ciint
39357db96d56Sopenharmony_ciPyDict_DelItemString(PyObject *v, const char *key)
39367db96d56Sopenharmony_ci{
39377db96d56Sopenharmony_ci    PyObject *kv;
39387db96d56Sopenharmony_ci    int err;
39397db96d56Sopenharmony_ci    kv = PyUnicode_FromString(key);
39407db96d56Sopenharmony_ci    if (kv == NULL)
39417db96d56Sopenharmony_ci        return -1;
39427db96d56Sopenharmony_ci    err = PyDict_DelItem(v, kv);
39437db96d56Sopenharmony_ci    Py_DECREF(kv);
39447db96d56Sopenharmony_ci    return err;
39457db96d56Sopenharmony_ci}
39467db96d56Sopenharmony_ci
39477db96d56Sopenharmony_ci/* Dictionary iterator types */
39487db96d56Sopenharmony_ci
39497db96d56Sopenharmony_citypedef struct {
39507db96d56Sopenharmony_ci    PyObject_HEAD
39517db96d56Sopenharmony_ci    PyDictObject *di_dict; /* Set to NULL when iterator is exhausted */
39527db96d56Sopenharmony_ci    Py_ssize_t di_used;
39537db96d56Sopenharmony_ci    Py_ssize_t di_pos;
39547db96d56Sopenharmony_ci    PyObject* di_result; /* reusable result tuple for iteritems */
39557db96d56Sopenharmony_ci    Py_ssize_t len;
39567db96d56Sopenharmony_ci} dictiterobject;
39577db96d56Sopenharmony_ci
39587db96d56Sopenharmony_cistatic PyObject *
39597db96d56Sopenharmony_cidictiter_new(PyDictObject *dict, PyTypeObject *itertype)
39607db96d56Sopenharmony_ci{
39617db96d56Sopenharmony_ci    dictiterobject *di;
39627db96d56Sopenharmony_ci    di = PyObject_GC_New(dictiterobject, itertype);
39637db96d56Sopenharmony_ci    if (di == NULL) {
39647db96d56Sopenharmony_ci        return NULL;
39657db96d56Sopenharmony_ci    }
39667db96d56Sopenharmony_ci    Py_INCREF(dict);
39677db96d56Sopenharmony_ci    di->di_dict = dict;
39687db96d56Sopenharmony_ci    di->di_used = dict->ma_used;
39697db96d56Sopenharmony_ci    di->len = dict->ma_used;
39707db96d56Sopenharmony_ci    if (itertype == &PyDictRevIterKey_Type ||
39717db96d56Sopenharmony_ci         itertype == &PyDictRevIterItem_Type ||
39727db96d56Sopenharmony_ci         itertype == &PyDictRevIterValue_Type) {
39737db96d56Sopenharmony_ci        if (dict->ma_values) {
39747db96d56Sopenharmony_ci            di->di_pos = dict->ma_used - 1;
39757db96d56Sopenharmony_ci        }
39767db96d56Sopenharmony_ci        else {
39777db96d56Sopenharmony_ci            di->di_pos = dict->ma_keys->dk_nentries - 1;
39787db96d56Sopenharmony_ci        }
39797db96d56Sopenharmony_ci    }
39807db96d56Sopenharmony_ci    else {
39817db96d56Sopenharmony_ci        di->di_pos = 0;
39827db96d56Sopenharmony_ci    }
39837db96d56Sopenharmony_ci    if (itertype == &PyDictIterItem_Type ||
39847db96d56Sopenharmony_ci        itertype == &PyDictRevIterItem_Type) {
39857db96d56Sopenharmony_ci        di->di_result = PyTuple_Pack(2, Py_None, Py_None);
39867db96d56Sopenharmony_ci        if (di->di_result == NULL) {
39877db96d56Sopenharmony_ci            Py_DECREF(di);
39887db96d56Sopenharmony_ci            return NULL;
39897db96d56Sopenharmony_ci        }
39907db96d56Sopenharmony_ci    }
39917db96d56Sopenharmony_ci    else {
39927db96d56Sopenharmony_ci        di->di_result = NULL;
39937db96d56Sopenharmony_ci    }
39947db96d56Sopenharmony_ci    _PyObject_GC_TRACK(di);
39957db96d56Sopenharmony_ci    return (PyObject *)di;
39967db96d56Sopenharmony_ci}
39977db96d56Sopenharmony_ci
39987db96d56Sopenharmony_cistatic void
39997db96d56Sopenharmony_cidictiter_dealloc(dictiterobject *di)
40007db96d56Sopenharmony_ci{
40017db96d56Sopenharmony_ci    /* bpo-31095: UnTrack is needed before calling any callbacks */
40027db96d56Sopenharmony_ci    _PyObject_GC_UNTRACK(di);
40037db96d56Sopenharmony_ci    Py_XDECREF(di->di_dict);
40047db96d56Sopenharmony_ci    Py_XDECREF(di->di_result);
40057db96d56Sopenharmony_ci    PyObject_GC_Del(di);
40067db96d56Sopenharmony_ci}
40077db96d56Sopenharmony_ci
40087db96d56Sopenharmony_cistatic int
40097db96d56Sopenharmony_cidictiter_traverse(dictiterobject *di, visitproc visit, void *arg)
40107db96d56Sopenharmony_ci{
40117db96d56Sopenharmony_ci    Py_VISIT(di->di_dict);
40127db96d56Sopenharmony_ci    Py_VISIT(di->di_result);
40137db96d56Sopenharmony_ci    return 0;
40147db96d56Sopenharmony_ci}
40157db96d56Sopenharmony_ci
40167db96d56Sopenharmony_cistatic PyObject *
40177db96d56Sopenharmony_cidictiter_len(dictiterobject *di, PyObject *Py_UNUSED(ignored))
40187db96d56Sopenharmony_ci{
40197db96d56Sopenharmony_ci    Py_ssize_t len = 0;
40207db96d56Sopenharmony_ci    if (di->di_dict != NULL && di->di_used == di->di_dict->ma_used)
40217db96d56Sopenharmony_ci        len = di->len;
40227db96d56Sopenharmony_ci    return PyLong_FromSize_t(len);
40237db96d56Sopenharmony_ci}
40247db96d56Sopenharmony_ci
40257db96d56Sopenharmony_ciPyDoc_STRVAR(length_hint_doc,
40267db96d56Sopenharmony_ci             "Private method returning an estimate of len(list(it)).");
40277db96d56Sopenharmony_ci
40287db96d56Sopenharmony_cistatic PyObject *
40297db96d56Sopenharmony_cidictiter_reduce(dictiterobject *di, PyObject *Py_UNUSED(ignored));
40307db96d56Sopenharmony_ci
40317db96d56Sopenharmony_ciPyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
40327db96d56Sopenharmony_ci
40337db96d56Sopenharmony_cistatic PyMethodDef dictiter_methods[] = {
40347db96d56Sopenharmony_ci    {"__length_hint__", _PyCFunction_CAST(dictiter_len), METH_NOARGS,
40357db96d56Sopenharmony_ci     length_hint_doc},
40367db96d56Sopenharmony_ci     {"__reduce__", _PyCFunction_CAST(dictiter_reduce), METH_NOARGS,
40377db96d56Sopenharmony_ci     reduce_doc},
40387db96d56Sopenharmony_ci    {NULL,              NULL}           /* sentinel */
40397db96d56Sopenharmony_ci};
40407db96d56Sopenharmony_ci
40417db96d56Sopenharmony_cistatic PyObject*
40427db96d56Sopenharmony_cidictiter_iternextkey(dictiterobject *di)
40437db96d56Sopenharmony_ci{
40447db96d56Sopenharmony_ci    PyObject *key;
40457db96d56Sopenharmony_ci    Py_ssize_t i;
40467db96d56Sopenharmony_ci    PyDictKeysObject *k;
40477db96d56Sopenharmony_ci    PyDictObject *d = di->di_dict;
40487db96d56Sopenharmony_ci
40497db96d56Sopenharmony_ci    if (d == NULL)
40507db96d56Sopenharmony_ci        return NULL;
40517db96d56Sopenharmony_ci    assert (PyDict_Check(d));
40527db96d56Sopenharmony_ci
40537db96d56Sopenharmony_ci    if (di->di_used != d->ma_used) {
40547db96d56Sopenharmony_ci        PyErr_SetString(PyExc_RuntimeError,
40557db96d56Sopenharmony_ci                        "dictionary changed size during iteration");
40567db96d56Sopenharmony_ci        di->di_used = -1; /* Make this state sticky */
40577db96d56Sopenharmony_ci        return NULL;
40587db96d56Sopenharmony_ci    }
40597db96d56Sopenharmony_ci
40607db96d56Sopenharmony_ci    i = di->di_pos;
40617db96d56Sopenharmony_ci    k = d->ma_keys;
40627db96d56Sopenharmony_ci    assert(i >= 0);
40637db96d56Sopenharmony_ci    if (d->ma_values) {
40647db96d56Sopenharmony_ci        if (i >= d->ma_used)
40657db96d56Sopenharmony_ci            goto fail;
40667db96d56Sopenharmony_ci        int index = get_index_from_order(d, i);
40677db96d56Sopenharmony_ci        key = DK_UNICODE_ENTRIES(k)[index].me_key;
40687db96d56Sopenharmony_ci        assert(d->ma_values->values[index] != NULL);
40697db96d56Sopenharmony_ci    }
40707db96d56Sopenharmony_ci    else {
40717db96d56Sopenharmony_ci        Py_ssize_t n = k->dk_nentries;
40727db96d56Sopenharmony_ci        if (DK_IS_UNICODE(k)) {
40737db96d56Sopenharmony_ci            PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(k)[i];
40747db96d56Sopenharmony_ci            while (i < n && entry_ptr->me_value == NULL) {
40757db96d56Sopenharmony_ci                entry_ptr++;
40767db96d56Sopenharmony_ci                i++;
40777db96d56Sopenharmony_ci            }
40787db96d56Sopenharmony_ci            if (i >= n)
40797db96d56Sopenharmony_ci                goto fail;
40807db96d56Sopenharmony_ci            key = entry_ptr->me_key;
40817db96d56Sopenharmony_ci        }
40827db96d56Sopenharmony_ci        else {
40837db96d56Sopenharmony_ci            PyDictKeyEntry *entry_ptr = &DK_ENTRIES(k)[i];
40847db96d56Sopenharmony_ci            while (i < n && entry_ptr->me_value == NULL) {
40857db96d56Sopenharmony_ci                entry_ptr++;
40867db96d56Sopenharmony_ci                i++;
40877db96d56Sopenharmony_ci            }
40887db96d56Sopenharmony_ci            if (i >= n)
40897db96d56Sopenharmony_ci                goto fail;
40907db96d56Sopenharmony_ci            key = entry_ptr->me_key;
40917db96d56Sopenharmony_ci        }
40927db96d56Sopenharmony_ci    }
40937db96d56Sopenharmony_ci    // We found an element (key), but did not expect it
40947db96d56Sopenharmony_ci    if (di->len == 0) {
40957db96d56Sopenharmony_ci        PyErr_SetString(PyExc_RuntimeError,
40967db96d56Sopenharmony_ci                        "dictionary keys changed during iteration");
40977db96d56Sopenharmony_ci        goto fail;
40987db96d56Sopenharmony_ci    }
40997db96d56Sopenharmony_ci    di->di_pos = i+1;
41007db96d56Sopenharmony_ci    di->len--;
41017db96d56Sopenharmony_ci    Py_INCREF(key);
41027db96d56Sopenharmony_ci    return key;
41037db96d56Sopenharmony_ci
41047db96d56Sopenharmony_cifail:
41057db96d56Sopenharmony_ci    di->di_dict = NULL;
41067db96d56Sopenharmony_ci    Py_DECREF(d);
41077db96d56Sopenharmony_ci    return NULL;
41087db96d56Sopenharmony_ci}
41097db96d56Sopenharmony_ci
41107db96d56Sopenharmony_ciPyTypeObject PyDictIterKey_Type = {
41117db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
41127db96d56Sopenharmony_ci    "dict_keyiterator",                         /* tp_name */
41137db96d56Sopenharmony_ci    sizeof(dictiterobject),                     /* tp_basicsize */
41147db96d56Sopenharmony_ci    0,                                          /* tp_itemsize */
41157db96d56Sopenharmony_ci    /* methods */
41167db96d56Sopenharmony_ci    (destructor)dictiter_dealloc,               /* tp_dealloc */
41177db96d56Sopenharmony_ci    0,                                          /* tp_vectorcall_offset */
41187db96d56Sopenharmony_ci    0,                                          /* tp_getattr */
41197db96d56Sopenharmony_ci    0,                                          /* tp_setattr */
41207db96d56Sopenharmony_ci    0,                                          /* tp_as_async */
41217db96d56Sopenharmony_ci    0,                                          /* tp_repr */
41227db96d56Sopenharmony_ci    0,                                          /* tp_as_number */
41237db96d56Sopenharmony_ci    0,                                          /* tp_as_sequence */
41247db96d56Sopenharmony_ci    0,                                          /* tp_as_mapping */
41257db96d56Sopenharmony_ci    0,                                          /* tp_hash */
41267db96d56Sopenharmony_ci    0,                                          /* tp_call */
41277db96d56Sopenharmony_ci    0,                                          /* tp_str */
41287db96d56Sopenharmony_ci    PyObject_GenericGetAttr,                    /* tp_getattro */
41297db96d56Sopenharmony_ci    0,                                          /* tp_setattro */
41307db96d56Sopenharmony_ci    0,                                          /* tp_as_buffer */
41317db96d56Sopenharmony_ci    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
41327db96d56Sopenharmony_ci    0,                                          /* tp_doc */
41337db96d56Sopenharmony_ci    (traverseproc)dictiter_traverse,            /* tp_traverse */
41347db96d56Sopenharmony_ci    0,                                          /* tp_clear */
41357db96d56Sopenharmony_ci    0,                                          /* tp_richcompare */
41367db96d56Sopenharmony_ci    0,                                          /* tp_weaklistoffset */
41377db96d56Sopenharmony_ci    PyObject_SelfIter,                          /* tp_iter */
41387db96d56Sopenharmony_ci    (iternextfunc)dictiter_iternextkey,         /* tp_iternext */
41397db96d56Sopenharmony_ci    dictiter_methods,                           /* tp_methods */
41407db96d56Sopenharmony_ci    0,
41417db96d56Sopenharmony_ci};
41427db96d56Sopenharmony_ci
41437db96d56Sopenharmony_cistatic PyObject *
41447db96d56Sopenharmony_cidictiter_iternextvalue(dictiterobject *di)
41457db96d56Sopenharmony_ci{
41467db96d56Sopenharmony_ci    PyObject *value;
41477db96d56Sopenharmony_ci    Py_ssize_t i;
41487db96d56Sopenharmony_ci    PyDictObject *d = di->di_dict;
41497db96d56Sopenharmony_ci
41507db96d56Sopenharmony_ci    if (d == NULL)
41517db96d56Sopenharmony_ci        return NULL;
41527db96d56Sopenharmony_ci    assert (PyDict_Check(d));
41537db96d56Sopenharmony_ci
41547db96d56Sopenharmony_ci    if (di->di_used != d->ma_used) {
41557db96d56Sopenharmony_ci        PyErr_SetString(PyExc_RuntimeError,
41567db96d56Sopenharmony_ci                        "dictionary changed size during iteration");
41577db96d56Sopenharmony_ci        di->di_used = -1; /* Make this state sticky */
41587db96d56Sopenharmony_ci        return NULL;
41597db96d56Sopenharmony_ci    }
41607db96d56Sopenharmony_ci
41617db96d56Sopenharmony_ci    i = di->di_pos;
41627db96d56Sopenharmony_ci    assert(i >= 0);
41637db96d56Sopenharmony_ci    if (d->ma_values) {
41647db96d56Sopenharmony_ci        if (i >= d->ma_used)
41657db96d56Sopenharmony_ci            goto fail;
41667db96d56Sopenharmony_ci        int index = get_index_from_order(d, i);
41677db96d56Sopenharmony_ci        value = d->ma_values->values[index];
41687db96d56Sopenharmony_ci        assert(value != NULL);
41697db96d56Sopenharmony_ci    }
41707db96d56Sopenharmony_ci    else {
41717db96d56Sopenharmony_ci        Py_ssize_t n = d->ma_keys->dk_nentries;
41727db96d56Sopenharmony_ci        if (DK_IS_UNICODE(d->ma_keys)) {
41737db96d56Sopenharmony_ci            PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(d->ma_keys)[i];
41747db96d56Sopenharmony_ci            while (i < n && entry_ptr->me_value == NULL) {
41757db96d56Sopenharmony_ci                entry_ptr++;
41767db96d56Sopenharmony_ci                i++;
41777db96d56Sopenharmony_ci            }
41787db96d56Sopenharmony_ci            if (i >= n)
41797db96d56Sopenharmony_ci                goto fail;
41807db96d56Sopenharmony_ci            value = entry_ptr->me_value;
41817db96d56Sopenharmony_ci        }
41827db96d56Sopenharmony_ci        else {
41837db96d56Sopenharmony_ci            PyDictKeyEntry *entry_ptr = &DK_ENTRIES(d->ma_keys)[i];
41847db96d56Sopenharmony_ci            while (i < n && entry_ptr->me_value == NULL) {
41857db96d56Sopenharmony_ci                entry_ptr++;
41867db96d56Sopenharmony_ci                i++;
41877db96d56Sopenharmony_ci            }
41887db96d56Sopenharmony_ci            if (i >= n)
41897db96d56Sopenharmony_ci                goto fail;
41907db96d56Sopenharmony_ci            value = entry_ptr->me_value;
41917db96d56Sopenharmony_ci        }
41927db96d56Sopenharmony_ci    }
41937db96d56Sopenharmony_ci    // We found an element, but did not expect it
41947db96d56Sopenharmony_ci    if (di->len == 0) {
41957db96d56Sopenharmony_ci        PyErr_SetString(PyExc_RuntimeError,
41967db96d56Sopenharmony_ci                        "dictionary keys changed during iteration");
41977db96d56Sopenharmony_ci        goto fail;
41987db96d56Sopenharmony_ci    }
41997db96d56Sopenharmony_ci    di->di_pos = i+1;
42007db96d56Sopenharmony_ci    di->len--;
42017db96d56Sopenharmony_ci    Py_INCREF(value);
42027db96d56Sopenharmony_ci    return value;
42037db96d56Sopenharmony_ci
42047db96d56Sopenharmony_cifail:
42057db96d56Sopenharmony_ci    di->di_dict = NULL;
42067db96d56Sopenharmony_ci    Py_DECREF(d);
42077db96d56Sopenharmony_ci    return NULL;
42087db96d56Sopenharmony_ci}
42097db96d56Sopenharmony_ci
42107db96d56Sopenharmony_ciPyTypeObject PyDictIterValue_Type = {
42117db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
42127db96d56Sopenharmony_ci    "dict_valueiterator",                       /* tp_name */
42137db96d56Sopenharmony_ci    sizeof(dictiterobject),                     /* tp_basicsize */
42147db96d56Sopenharmony_ci    0,                                          /* tp_itemsize */
42157db96d56Sopenharmony_ci    /* methods */
42167db96d56Sopenharmony_ci    (destructor)dictiter_dealloc,               /* tp_dealloc */
42177db96d56Sopenharmony_ci    0,                                          /* tp_vectorcall_offset */
42187db96d56Sopenharmony_ci    0,                                          /* tp_getattr */
42197db96d56Sopenharmony_ci    0,                                          /* tp_setattr */
42207db96d56Sopenharmony_ci    0,                                          /* tp_as_async */
42217db96d56Sopenharmony_ci    0,                                          /* tp_repr */
42227db96d56Sopenharmony_ci    0,                                          /* tp_as_number */
42237db96d56Sopenharmony_ci    0,                                          /* tp_as_sequence */
42247db96d56Sopenharmony_ci    0,                                          /* tp_as_mapping */
42257db96d56Sopenharmony_ci    0,                                          /* tp_hash */
42267db96d56Sopenharmony_ci    0,                                          /* tp_call */
42277db96d56Sopenharmony_ci    0,                                          /* tp_str */
42287db96d56Sopenharmony_ci    PyObject_GenericGetAttr,                    /* tp_getattro */
42297db96d56Sopenharmony_ci    0,                                          /* tp_setattro */
42307db96d56Sopenharmony_ci    0,                                          /* tp_as_buffer */
42317db96d56Sopenharmony_ci    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
42327db96d56Sopenharmony_ci    0,                                          /* tp_doc */
42337db96d56Sopenharmony_ci    (traverseproc)dictiter_traverse,            /* tp_traverse */
42347db96d56Sopenharmony_ci    0,                                          /* tp_clear */
42357db96d56Sopenharmony_ci    0,                                          /* tp_richcompare */
42367db96d56Sopenharmony_ci    0,                                          /* tp_weaklistoffset */
42377db96d56Sopenharmony_ci    PyObject_SelfIter,                          /* tp_iter */
42387db96d56Sopenharmony_ci    (iternextfunc)dictiter_iternextvalue,       /* tp_iternext */
42397db96d56Sopenharmony_ci    dictiter_methods,                           /* tp_methods */
42407db96d56Sopenharmony_ci    0,
42417db96d56Sopenharmony_ci};
42427db96d56Sopenharmony_ci
42437db96d56Sopenharmony_cistatic PyObject *
42447db96d56Sopenharmony_cidictiter_iternextitem(dictiterobject *di)
42457db96d56Sopenharmony_ci{
42467db96d56Sopenharmony_ci    PyObject *key, *value, *result;
42477db96d56Sopenharmony_ci    Py_ssize_t i;
42487db96d56Sopenharmony_ci    PyDictObject *d = di->di_dict;
42497db96d56Sopenharmony_ci
42507db96d56Sopenharmony_ci    if (d == NULL)
42517db96d56Sopenharmony_ci        return NULL;
42527db96d56Sopenharmony_ci    assert (PyDict_Check(d));
42537db96d56Sopenharmony_ci
42547db96d56Sopenharmony_ci    if (di->di_used != d->ma_used) {
42557db96d56Sopenharmony_ci        PyErr_SetString(PyExc_RuntimeError,
42567db96d56Sopenharmony_ci                        "dictionary changed size during iteration");
42577db96d56Sopenharmony_ci        di->di_used = -1; /* Make this state sticky */
42587db96d56Sopenharmony_ci        return NULL;
42597db96d56Sopenharmony_ci    }
42607db96d56Sopenharmony_ci
42617db96d56Sopenharmony_ci    i = di->di_pos;
42627db96d56Sopenharmony_ci    assert(i >= 0);
42637db96d56Sopenharmony_ci    if (d->ma_values) {
42647db96d56Sopenharmony_ci        if (i >= d->ma_used)
42657db96d56Sopenharmony_ci            goto fail;
42667db96d56Sopenharmony_ci        int index = get_index_from_order(d, i);
42677db96d56Sopenharmony_ci        key = DK_UNICODE_ENTRIES(d->ma_keys)[index].me_key;
42687db96d56Sopenharmony_ci        value = d->ma_values->values[index];
42697db96d56Sopenharmony_ci        assert(value != NULL);
42707db96d56Sopenharmony_ci    }
42717db96d56Sopenharmony_ci    else {
42727db96d56Sopenharmony_ci        Py_ssize_t n = d->ma_keys->dk_nentries;
42737db96d56Sopenharmony_ci        if (DK_IS_UNICODE(d->ma_keys)) {
42747db96d56Sopenharmony_ci            PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(d->ma_keys)[i];
42757db96d56Sopenharmony_ci            while (i < n && entry_ptr->me_value == NULL) {
42767db96d56Sopenharmony_ci                entry_ptr++;
42777db96d56Sopenharmony_ci                i++;
42787db96d56Sopenharmony_ci            }
42797db96d56Sopenharmony_ci            if (i >= n)
42807db96d56Sopenharmony_ci                goto fail;
42817db96d56Sopenharmony_ci            key = entry_ptr->me_key;
42827db96d56Sopenharmony_ci            value = entry_ptr->me_value;
42837db96d56Sopenharmony_ci        }
42847db96d56Sopenharmony_ci        else {
42857db96d56Sopenharmony_ci            PyDictKeyEntry *entry_ptr = &DK_ENTRIES(d->ma_keys)[i];
42867db96d56Sopenharmony_ci            while (i < n && entry_ptr->me_value == NULL) {
42877db96d56Sopenharmony_ci                entry_ptr++;
42887db96d56Sopenharmony_ci                i++;
42897db96d56Sopenharmony_ci            }
42907db96d56Sopenharmony_ci            if (i >= n)
42917db96d56Sopenharmony_ci                goto fail;
42927db96d56Sopenharmony_ci            key = entry_ptr->me_key;
42937db96d56Sopenharmony_ci            value = entry_ptr->me_value;
42947db96d56Sopenharmony_ci        }
42957db96d56Sopenharmony_ci    }
42967db96d56Sopenharmony_ci    // We found an element, but did not expect it
42977db96d56Sopenharmony_ci    if (di->len == 0) {
42987db96d56Sopenharmony_ci        PyErr_SetString(PyExc_RuntimeError,
42997db96d56Sopenharmony_ci                        "dictionary keys changed during iteration");
43007db96d56Sopenharmony_ci        goto fail;
43017db96d56Sopenharmony_ci    }
43027db96d56Sopenharmony_ci    di->di_pos = i+1;
43037db96d56Sopenharmony_ci    di->len--;
43047db96d56Sopenharmony_ci    Py_INCREF(key);
43057db96d56Sopenharmony_ci    Py_INCREF(value);
43067db96d56Sopenharmony_ci    result = di->di_result;
43077db96d56Sopenharmony_ci    if (Py_REFCNT(result) == 1) {
43087db96d56Sopenharmony_ci        PyObject *oldkey = PyTuple_GET_ITEM(result, 0);
43097db96d56Sopenharmony_ci        PyObject *oldvalue = PyTuple_GET_ITEM(result, 1);
43107db96d56Sopenharmony_ci        PyTuple_SET_ITEM(result, 0, key);  /* steals reference */
43117db96d56Sopenharmony_ci        PyTuple_SET_ITEM(result, 1, value);  /* steals reference */
43127db96d56Sopenharmony_ci        Py_INCREF(result);
43137db96d56Sopenharmony_ci        Py_DECREF(oldkey);
43147db96d56Sopenharmony_ci        Py_DECREF(oldvalue);
43157db96d56Sopenharmony_ci        // bpo-42536: The GC may have untracked this result tuple. Since we're
43167db96d56Sopenharmony_ci        // recycling it, make sure it's tracked again:
43177db96d56Sopenharmony_ci        if (!_PyObject_GC_IS_TRACKED(result)) {
43187db96d56Sopenharmony_ci            _PyObject_GC_TRACK(result);
43197db96d56Sopenharmony_ci        }
43207db96d56Sopenharmony_ci    }
43217db96d56Sopenharmony_ci    else {
43227db96d56Sopenharmony_ci        result = PyTuple_New(2);
43237db96d56Sopenharmony_ci        if (result == NULL)
43247db96d56Sopenharmony_ci            return NULL;
43257db96d56Sopenharmony_ci        PyTuple_SET_ITEM(result, 0, key);  /* steals reference */
43267db96d56Sopenharmony_ci        PyTuple_SET_ITEM(result, 1, value);  /* steals reference */
43277db96d56Sopenharmony_ci    }
43287db96d56Sopenharmony_ci    return result;
43297db96d56Sopenharmony_ci
43307db96d56Sopenharmony_cifail:
43317db96d56Sopenharmony_ci    di->di_dict = NULL;
43327db96d56Sopenharmony_ci    Py_DECREF(d);
43337db96d56Sopenharmony_ci    return NULL;
43347db96d56Sopenharmony_ci}
43357db96d56Sopenharmony_ci
43367db96d56Sopenharmony_ciPyTypeObject PyDictIterItem_Type = {
43377db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
43387db96d56Sopenharmony_ci    "dict_itemiterator",                        /* tp_name */
43397db96d56Sopenharmony_ci    sizeof(dictiterobject),                     /* tp_basicsize */
43407db96d56Sopenharmony_ci    0,                                          /* tp_itemsize */
43417db96d56Sopenharmony_ci    /* methods */
43427db96d56Sopenharmony_ci    (destructor)dictiter_dealloc,               /* tp_dealloc */
43437db96d56Sopenharmony_ci    0,                                          /* tp_vectorcall_offset */
43447db96d56Sopenharmony_ci    0,                                          /* tp_getattr */
43457db96d56Sopenharmony_ci    0,                                          /* tp_setattr */
43467db96d56Sopenharmony_ci    0,                                          /* tp_as_async */
43477db96d56Sopenharmony_ci    0,                                          /* tp_repr */
43487db96d56Sopenharmony_ci    0,                                          /* tp_as_number */
43497db96d56Sopenharmony_ci    0,                                          /* tp_as_sequence */
43507db96d56Sopenharmony_ci    0,                                          /* tp_as_mapping */
43517db96d56Sopenharmony_ci    0,                                          /* tp_hash */
43527db96d56Sopenharmony_ci    0,                                          /* tp_call */
43537db96d56Sopenharmony_ci    0,                                          /* tp_str */
43547db96d56Sopenharmony_ci    PyObject_GenericGetAttr,                    /* tp_getattro */
43557db96d56Sopenharmony_ci    0,                                          /* tp_setattro */
43567db96d56Sopenharmony_ci    0,                                          /* tp_as_buffer */
43577db96d56Sopenharmony_ci    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
43587db96d56Sopenharmony_ci    0,                                          /* tp_doc */
43597db96d56Sopenharmony_ci    (traverseproc)dictiter_traverse,            /* tp_traverse */
43607db96d56Sopenharmony_ci    0,                                          /* tp_clear */
43617db96d56Sopenharmony_ci    0,                                          /* tp_richcompare */
43627db96d56Sopenharmony_ci    0,                                          /* tp_weaklistoffset */
43637db96d56Sopenharmony_ci    PyObject_SelfIter,                          /* tp_iter */
43647db96d56Sopenharmony_ci    (iternextfunc)dictiter_iternextitem,        /* tp_iternext */
43657db96d56Sopenharmony_ci    dictiter_methods,                           /* tp_methods */
43667db96d56Sopenharmony_ci    0,
43677db96d56Sopenharmony_ci};
43687db96d56Sopenharmony_ci
43697db96d56Sopenharmony_ci
43707db96d56Sopenharmony_ci/* dictreviter */
43717db96d56Sopenharmony_ci
43727db96d56Sopenharmony_cistatic PyObject *
43737db96d56Sopenharmony_cidictreviter_iternext(dictiterobject *di)
43747db96d56Sopenharmony_ci{
43757db96d56Sopenharmony_ci    PyDictObject *d = di->di_dict;
43767db96d56Sopenharmony_ci
43777db96d56Sopenharmony_ci    if (d == NULL) {
43787db96d56Sopenharmony_ci        return NULL;
43797db96d56Sopenharmony_ci    }
43807db96d56Sopenharmony_ci    assert (PyDict_Check(d));
43817db96d56Sopenharmony_ci
43827db96d56Sopenharmony_ci    if (di->di_used != d->ma_used) {
43837db96d56Sopenharmony_ci        PyErr_SetString(PyExc_RuntimeError,
43847db96d56Sopenharmony_ci                         "dictionary changed size during iteration");
43857db96d56Sopenharmony_ci        di->di_used = -1; /* Make this state sticky */
43867db96d56Sopenharmony_ci        return NULL;
43877db96d56Sopenharmony_ci    }
43887db96d56Sopenharmony_ci
43897db96d56Sopenharmony_ci    Py_ssize_t i = di->di_pos;
43907db96d56Sopenharmony_ci    PyDictKeysObject *k = d->ma_keys;
43917db96d56Sopenharmony_ci    PyObject *key, *value, *result;
43927db96d56Sopenharmony_ci
43937db96d56Sopenharmony_ci    if (i < 0) {
43947db96d56Sopenharmony_ci        goto fail;
43957db96d56Sopenharmony_ci    }
43967db96d56Sopenharmony_ci    if (d->ma_values) {
43977db96d56Sopenharmony_ci        int index = get_index_from_order(d, i);
43987db96d56Sopenharmony_ci        key = DK_UNICODE_ENTRIES(k)[index].me_key;
43997db96d56Sopenharmony_ci        value = d->ma_values->values[index];
44007db96d56Sopenharmony_ci        assert (value != NULL);
44017db96d56Sopenharmony_ci    }
44027db96d56Sopenharmony_ci    else {
44037db96d56Sopenharmony_ci        if (DK_IS_UNICODE(k)) {
44047db96d56Sopenharmony_ci            PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(k)[i];
44057db96d56Sopenharmony_ci            while (entry_ptr->me_value == NULL) {
44067db96d56Sopenharmony_ci                if (--i < 0) {
44077db96d56Sopenharmony_ci                    goto fail;
44087db96d56Sopenharmony_ci                }
44097db96d56Sopenharmony_ci                entry_ptr--;
44107db96d56Sopenharmony_ci            }
44117db96d56Sopenharmony_ci            key = entry_ptr->me_key;
44127db96d56Sopenharmony_ci            value = entry_ptr->me_value;
44137db96d56Sopenharmony_ci        }
44147db96d56Sopenharmony_ci        else {
44157db96d56Sopenharmony_ci            PyDictKeyEntry *entry_ptr = &DK_ENTRIES(k)[i];
44167db96d56Sopenharmony_ci            while (entry_ptr->me_value == NULL) {
44177db96d56Sopenharmony_ci                if (--i < 0) {
44187db96d56Sopenharmony_ci                    goto fail;
44197db96d56Sopenharmony_ci                }
44207db96d56Sopenharmony_ci                entry_ptr--;
44217db96d56Sopenharmony_ci            }
44227db96d56Sopenharmony_ci            key = entry_ptr->me_key;
44237db96d56Sopenharmony_ci            value = entry_ptr->me_value;
44247db96d56Sopenharmony_ci        }
44257db96d56Sopenharmony_ci    }
44267db96d56Sopenharmony_ci    di->di_pos = i-1;
44277db96d56Sopenharmony_ci    di->len--;
44287db96d56Sopenharmony_ci
44297db96d56Sopenharmony_ci    if (Py_IS_TYPE(di, &PyDictRevIterKey_Type)) {
44307db96d56Sopenharmony_ci        Py_INCREF(key);
44317db96d56Sopenharmony_ci        return key;
44327db96d56Sopenharmony_ci    }
44337db96d56Sopenharmony_ci    else if (Py_IS_TYPE(di, &PyDictRevIterValue_Type)) {
44347db96d56Sopenharmony_ci        Py_INCREF(value);
44357db96d56Sopenharmony_ci        return value;
44367db96d56Sopenharmony_ci    }
44377db96d56Sopenharmony_ci    else if (Py_IS_TYPE(di, &PyDictRevIterItem_Type)) {
44387db96d56Sopenharmony_ci        Py_INCREF(key);
44397db96d56Sopenharmony_ci        Py_INCREF(value);
44407db96d56Sopenharmony_ci        result = di->di_result;
44417db96d56Sopenharmony_ci        if (Py_REFCNT(result) == 1) {
44427db96d56Sopenharmony_ci            PyObject *oldkey = PyTuple_GET_ITEM(result, 0);
44437db96d56Sopenharmony_ci            PyObject *oldvalue = PyTuple_GET_ITEM(result, 1);
44447db96d56Sopenharmony_ci            PyTuple_SET_ITEM(result, 0, key);  /* steals reference */
44457db96d56Sopenharmony_ci            PyTuple_SET_ITEM(result, 1, value);  /* steals reference */
44467db96d56Sopenharmony_ci            Py_INCREF(result);
44477db96d56Sopenharmony_ci            Py_DECREF(oldkey);
44487db96d56Sopenharmony_ci            Py_DECREF(oldvalue);
44497db96d56Sopenharmony_ci            // bpo-42536: The GC may have untracked this result tuple. Since
44507db96d56Sopenharmony_ci            // we're recycling it, make sure it's tracked again:
44517db96d56Sopenharmony_ci            if (!_PyObject_GC_IS_TRACKED(result)) {
44527db96d56Sopenharmony_ci                _PyObject_GC_TRACK(result);
44537db96d56Sopenharmony_ci            }
44547db96d56Sopenharmony_ci        }
44557db96d56Sopenharmony_ci        else {
44567db96d56Sopenharmony_ci            result = PyTuple_New(2);
44577db96d56Sopenharmony_ci            if (result == NULL) {
44587db96d56Sopenharmony_ci                return NULL;
44597db96d56Sopenharmony_ci            }
44607db96d56Sopenharmony_ci            PyTuple_SET_ITEM(result, 0, key); /* steals reference */
44617db96d56Sopenharmony_ci            PyTuple_SET_ITEM(result, 1, value); /* steals reference */
44627db96d56Sopenharmony_ci        }
44637db96d56Sopenharmony_ci        return result;
44647db96d56Sopenharmony_ci    }
44657db96d56Sopenharmony_ci    else {
44667db96d56Sopenharmony_ci        Py_UNREACHABLE();
44677db96d56Sopenharmony_ci    }
44687db96d56Sopenharmony_ci
44697db96d56Sopenharmony_cifail:
44707db96d56Sopenharmony_ci    di->di_dict = NULL;
44717db96d56Sopenharmony_ci    Py_DECREF(d);
44727db96d56Sopenharmony_ci    return NULL;
44737db96d56Sopenharmony_ci}
44747db96d56Sopenharmony_ci
44757db96d56Sopenharmony_ciPyTypeObject PyDictRevIterKey_Type = {
44767db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
44777db96d56Sopenharmony_ci    "dict_reversekeyiterator",
44787db96d56Sopenharmony_ci    sizeof(dictiterobject),
44797db96d56Sopenharmony_ci    .tp_dealloc = (destructor)dictiter_dealloc,
44807db96d56Sopenharmony_ci    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
44817db96d56Sopenharmony_ci    .tp_traverse = (traverseproc)dictiter_traverse,
44827db96d56Sopenharmony_ci    .tp_iter = PyObject_SelfIter,
44837db96d56Sopenharmony_ci    .tp_iternext = (iternextfunc)dictreviter_iternext,
44847db96d56Sopenharmony_ci    .tp_methods = dictiter_methods
44857db96d56Sopenharmony_ci};
44867db96d56Sopenharmony_ci
44877db96d56Sopenharmony_ci
44887db96d56Sopenharmony_ci/*[clinic input]
44897db96d56Sopenharmony_cidict.__reversed__
44907db96d56Sopenharmony_ci
44917db96d56Sopenharmony_ciReturn a reverse iterator over the dict keys.
44927db96d56Sopenharmony_ci[clinic start generated code]*/
44937db96d56Sopenharmony_ci
44947db96d56Sopenharmony_cistatic PyObject *
44957db96d56Sopenharmony_cidict___reversed___impl(PyDictObject *self)
44967db96d56Sopenharmony_ci/*[clinic end generated code: output=e674483336d1ed51 input=23210ef3477d8c4d]*/
44977db96d56Sopenharmony_ci{
44987db96d56Sopenharmony_ci    assert (PyDict_Check(self));
44997db96d56Sopenharmony_ci    return dictiter_new(self, &PyDictRevIterKey_Type);
45007db96d56Sopenharmony_ci}
45017db96d56Sopenharmony_ci
45027db96d56Sopenharmony_cistatic PyObject *
45037db96d56Sopenharmony_cidictiter_reduce(dictiterobject *di, PyObject *Py_UNUSED(ignored))
45047db96d56Sopenharmony_ci{
45057db96d56Sopenharmony_ci    /* copy the iterator state */
45067db96d56Sopenharmony_ci    dictiterobject tmp = *di;
45077db96d56Sopenharmony_ci    Py_XINCREF(tmp.di_dict);
45087db96d56Sopenharmony_ci
45097db96d56Sopenharmony_ci    PyObject *list = PySequence_List((PyObject*)&tmp);
45107db96d56Sopenharmony_ci    Py_XDECREF(tmp.di_dict);
45117db96d56Sopenharmony_ci    if (list == NULL) {
45127db96d56Sopenharmony_ci        return NULL;
45137db96d56Sopenharmony_ci    }
45147db96d56Sopenharmony_ci    return Py_BuildValue("N(N)", _PyEval_GetBuiltin(&_Py_ID(iter)), list);
45157db96d56Sopenharmony_ci}
45167db96d56Sopenharmony_ci
45177db96d56Sopenharmony_ciPyTypeObject PyDictRevIterItem_Type = {
45187db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
45197db96d56Sopenharmony_ci    "dict_reverseitemiterator",
45207db96d56Sopenharmony_ci    sizeof(dictiterobject),
45217db96d56Sopenharmony_ci    .tp_dealloc = (destructor)dictiter_dealloc,
45227db96d56Sopenharmony_ci    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
45237db96d56Sopenharmony_ci    .tp_traverse = (traverseproc)dictiter_traverse,
45247db96d56Sopenharmony_ci    .tp_iter = PyObject_SelfIter,
45257db96d56Sopenharmony_ci    .tp_iternext = (iternextfunc)dictreviter_iternext,
45267db96d56Sopenharmony_ci    .tp_methods = dictiter_methods
45277db96d56Sopenharmony_ci};
45287db96d56Sopenharmony_ci
45297db96d56Sopenharmony_ciPyTypeObject PyDictRevIterValue_Type = {
45307db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
45317db96d56Sopenharmony_ci    "dict_reversevalueiterator",
45327db96d56Sopenharmony_ci    sizeof(dictiterobject),
45337db96d56Sopenharmony_ci    .tp_dealloc = (destructor)dictiter_dealloc,
45347db96d56Sopenharmony_ci    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
45357db96d56Sopenharmony_ci    .tp_traverse = (traverseproc)dictiter_traverse,
45367db96d56Sopenharmony_ci    .tp_iter = PyObject_SelfIter,
45377db96d56Sopenharmony_ci    .tp_iternext = (iternextfunc)dictreviter_iternext,
45387db96d56Sopenharmony_ci    .tp_methods = dictiter_methods
45397db96d56Sopenharmony_ci};
45407db96d56Sopenharmony_ci
45417db96d56Sopenharmony_ci/***********************************************/
45427db96d56Sopenharmony_ci/* View objects for keys(), items(), values(). */
45437db96d56Sopenharmony_ci/***********************************************/
45447db96d56Sopenharmony_ci
45457db96d56Sopenharmony_ci/* The instance lay-out is the same for all three; but the type differs. */
45467db96d56Sopenharmony_ci
45477db96d56Sopenharmony_cistatic void
45487db96d56Sopenharmony_cidictview_dealloc(_PyDictViewObject *dv)
45497db96d56Sopenharmony_ci{
45507db96d56Sopenharmony_ci    /* bpo-31095: UnTrack is needed before calling any callbacks */
45517db96d56Sopenharmony_ci    _PyObject_GC_UNTRACK(dv);
45527db96d56Sopenharmony_ci    Py_XDECREF(dv->dv_dict);
45537db96d56Sopenharmony_ci    PyObject_GC_Del(dv);
45547db96d56Sopenharmony_ci}
45557db96d56Sopenharmony_ci
45567db96d56Sopenharmony_cistatic int
45577db96d56Sopenharmony_cidictview_traverse(_PyDictViewObject *dv, visitproc visit, void *arg)
45587db96d56Sopenharmony_ci{
45597db96d56Sopenharmony_ci    Py_VISIT(dv->dv_dict);
45607db96d56Sopenharmony_ci    return 0;
45617db96d56Sopenharmony_ci}
45627db96d56Sopenharmony_ci
45637db96d56Sopenharmony_cistatic Py_ssize_t
45647db96d56Sopenharmony_cidictview_len(_PyDictViewObject *dv)
45657db96d56Sopenharmony_ci{
45667db96d56Sopenharmony_ci    Py_ssize_t len = 0;
45677db96d56Sopenharmony_ci    if (dv->dv_dict != NULL)
45687db96d56Sopenharmony_ci        len = dv->dv_dict->ma_used;
45697db96d56Sopenharmony_ci    return len;
45707db96d56Sopenharmony_ci}
45717db96d56Sopenharmony_ci
45727db96d56Sopenharmony_ciPyObject *
45737db96d56Sopenharmony_ci_PyDictView_New(PyObject *dict, PyTypeObject *type)
45747db96d56Sopenharmony_ci{
45757db96d56Sopenharmony_ci    _PyDictViewObject *dv;
45767db96d56Sopenharmony_ci    if (dict == NULL) {
45777db96d56Sopenharmony_ci        PyErr_BadInternalCall();
45787db96d56Sopenharmony_ci        return NULL;
45797db96d56Sopenharmony_ci    }
45807db96d56Sopenharmony_ci    if (!PyDict_Check(dict)) {
45817db96d56Sopenharmony_ci        /* XXX Get rid of this restriction later */
45827db96d56Sopenharmony_ci        PyErr_Format(PyExc_TypeError,
45837db96d56Sopenharmony_ci                     "%s() requires a dict argument, not '%s'",
45847db96d56Sopenharmony_ci                     type->tp_name, Py_TYPE(dict)->tp_name);
45857db96d56Sopenharmony_ci        return NULL;
45867db96d56Sopenharmony_ci    }
45877db96d56Sopenharmony_ci    dv = PyObject_GC_New(_PyDictViewObject, type);
45887db96d56Sopenharmony_ci    if (dv == NULL)
45897db96d56Sopenharmony_ci        return NULL;
45907db96d56Sopenharmony_ci    Py_INCREF(dict);
45917db96d56Sopenharmony_ci    dv->dv_dict = (PyDictObject *)dict;
45927db96d56Sopenharmony_ci    _PyObject_GC_TRACK(dv);
45937db96d56Sopenharmony_ci    return (PyObject *)dv;
45947db96d56Sopenharmony_ci}
45957db96d56Sopenharmony_ci
45967db96d56Sopenharmony_cistatic PyObject *
45977db96d56Sopenharmony_cidictview_mapping(PyObject *view, void *Py_UNUSED(ignored)) {
45987db96d56Sopenharmony_ci    assert(view != NULL);
45997db96d56Sopenharmony_ci    assert(PyDictKeys_Check(view)
46007db96d56Sopenharmony_ci           || PyDictValues_Check(view)
46017db96d56Sopenharmony_ci           || PyDictItems_Check(view));
46027db96d56Sopenharmony_ci    PyObject *mapping = (PyObject *)((_PyDictViewObject *)view)->dv_dict;
46037db96d56Sopenharmony_ci    return PyDictProxy_New(mapping);
46047db96d56Sopenharmony_ci}
46057db96d56Sopenharmony_ci
46067db96d56Sopenharmony_cistatic PyGetSetDef dictview_getset[] = {
46077db96d56Sopenharmony_ci    {"mapping", dictview_mapping, (setter)NULL,
46087db96d56Sopenharmony_ci     "dictionary that this view refers to", NULL},
46097db96d56Sopenharmony_ci    {0}
46107db96d56Sopenharmony_ci};
46117db96d56Sopenharmony_ci
46127db96d56Sopenharmony_ci/* TODO(guido): The views objects are not complete:
46137db96d56Sopenharmony_ci
46147db96d56Sopenharmony_ci * support more set operations
46157db96d56Sopenharmony_ci * support arbitrary mappings?
46167db96d56Sopenharmony_ci   - either these should be static or exported in dictobject.h
46177db96d56Sopenharmony_ci   - if public then they should probably be in builtins
46187db96d56Sopenharmony_ci*/
46197db96d56Sopenharmony_ci
46207db96d56Sopenharmony_ci/* Return 1 if self is a subset of other, iterating over self;
46217db96d56Sopenharmony_ci   0 if not; -1 if an error occurred. */
46227db96d56Sopenharmony_cistatic int
46237db96d56Sopenharmony_ciall_contained_in(PyObject *self, PyObject *other)
46247db96d56Sopenharmony_ci{
46257db96d56Sopenharmony_ci    PyObject *iter = PyObject_GetIter(self);
46267db96d56Sopenharmony_ci    int ok = 1;
46277db96d56Sopenharmony_ci
46287db96d56Sopenharmony_ci    if (iter == NULL)
46297db96d56Sopenharmony_ci        return -1;
46307db96d56Sopenharmony_ci    for (;;) {
46317db96d56Sopenharmony_ci        PyObject *next = PyIter_Next(iter);
46327db96d56Sopenharmony_ci        if (next == NULL) {
46337db96d56Sopenharmony_ci            if (PyErr_Occurred())
46347db96d56Sopenharmony_ci                ok = -1;
46357db96d56Sopenharmony_ci            break;
46367db96d56Sopenharmony_ci        }
46377db96d56Sopenharmony_ci        ok = PySequence_Contains(other, next);
46387db96d56Sopenharmony_ci        Py_DECREF(next);
46397db96d56Sopenharmony_ci        if (ok <= 0)
46407db96d56Sopenharmony_ci            break;
46417db96d56Sopenharmony_ci    }
46427db96d56Sopenharmony_ci    Py_DECREF(iter);
46437db96d56Sopenharmony_ci    return ok;
46447db96d56Sopenharmony_ci}
46457db96d56Sopenharmony_ci
46467db96d56Sopenharmony_cistatic PyObject *
46477db96d56Sopenharmony_cidictview_richcompare(PyObject *self, PyObject *other, int op)
46487db96d56Sopenharmony_ci{
46497db96d56Sopenharmony_ci    Py_ssize_t len_self, len_other;
46507db96d56Sopenharmony_ci    int ok;
46517db96d56Sopenharmony_ci    PyObject *result;
46527db96d56Sopenharmony_ci
46537db96d56Sopenharmony_ci    assert(self != NULL);
46547db96d56Sopenharmony_ci    assert(PyDictViewSet_Check(self));
46557db96d56Sopenharmony_ci    assert(other != NULL);
46567db96d56Sopenharmony_ci
46577db96d56Sopenharmony_ci    if (!PyAnySet_Check(other) && !PyDictViewSet_Check(other))
46587db96d56Sopenharmony_ci        Py_RETURN_NOTIMPLEMENTED;
46597db96d56Sopenharmony_ci
46607db96d56Sopenharmony_ci    len_self = PyObject_Size(self);
46617db96d56Sopenharmony_ci    if (len_self < 0)
46627db96d56Sopenharmony_ci        return NULL;
46637db96d56Sopenharmony_ci    len_other = PyObject_Size(other);
46647db96d56Sopenharmony_ci    if (len_other < 0)
46657db96d56Sopenharmony_ci        return NULL;
46667db96d56Sopenharmony_ci
46677db96d56Sopenharmony_ci    ok = 0;
46687db96d56Sopenharmony_ci    switch(op) {
46697db96d56Sopenharmony_ci
46707db96d56Sopenharmony_ci    case Py_NE:
46717db96d56Sopenharmony_ci    case Py_EQ:
46727db96d56Sopenharmony_ci        if (len_self == len_other)
46737db96d56Sopenharmony_ci            ok = all_contained_in(self, other);
46747db96d56Sopenharmony_ci        if (op == Py_NE && ok >= 0)
46757db96d56Sopenharmony_ci            ok = !ok;
46767db96d56Sopenharmony_ci        break;
46777db96d56Sopenharmony_ci
46787db96d56Sopenharmony_ci    case Py_LT:
46797db96d56Sopenharmony_ci        if (len_self < len_other)
46807db96d56Sopenharmony_ci            ok = all_contained_in(self, other);
46817db96d56Sopenharmony_ci        break;
46827db96d56Sopenharmony_ci
46837db96d56Sopenharmony_ci      case Py_LE:
46847db96d56Sopenharmony_ci          if (len_self <= len_other)
46857db96d56Sopenharmony_ci              ok = all_contained_in(self, other);
46867db96d56Sopenharmony_ci          break;
46877db96d56Sopenharmony_ci
46887db96d56Sopenharmony_ci    case Py_GT:
46897db96d56Sopenharmony_ci        if (len_self > len_other)
46907db96d56Sopenharmony_ci            ok = all_contained_in(other, self);
46917db96d56Sopenharmony_ci        break;
46927db96d56Sopenharmony_ci
46937db96d56Sopenharmony_ci    case Py_GE:
46947db96d56Sopenharmony_ci        if (len_self >= len_other)
46957db96d56Sopenharmony_ci            ok = all_contained_in(other, self);
46967db96d56Sopenharmony_ci        break;
46977db96d56Sopenharmony_ci
46987db96d56Sopenharmony_ci    }
46997db96d56Sopenharmony_ci    if (ok < 0)
47007db96d56Sopenharmony_ci        return NULL;
47017db96d56Sopenharmony_ci    result = ok ? Py_True : Py_False;
47027db96d56Sopenharmony_ci    Py_INCREF(result);
47037db96d56Sopenharmony_ci    return result;
47047db96d56Sopenharmony_ci}
47057db96d56Sopenharmony_ci
47067db96d56Sopenharmony_cistatic PyObject *
47077db96d56Sopenharmony_cidictview_repr(_PyDictViewObject *dv)
47087db96d56Sopenharmony_ci{
47097db96d56Sopenharmony_ci    PyObject *seq;
47107db96d56Sopenharmony_ci    PyObject *result = NULL;
47117db96d56Sopenharmony_ci    Py_ssize_t rc;
47127db96d56Sopenharmony_ci
47137db96d56Sopenharmony_ci    rc = Py_ReprEnter((PyObject *)dv);
47147db96d56Sopenharmony_ci    if (rc != 0) {
47157db96d56Sopenharmony_ci        return rc > 0 ? PyUnicode_FromString("...") : NULL;
47167db96d56Sopenharmony_ci    }
47177db96d56Sopenharmony_ci    seq = PySequence_List((PyObject *)dv);
47187db96d56Sopenharmony_ci    if (seq == NULL) {
47197db96d56Sopenharmony_ci        goto Done;
47207db96d56Sopenharmony_ci    }
47217db96d56Sopenharmony_ci    result = PyUnicode_FromFormat("%s(%R)", Py_TYPE(dv)->tp_name, seq);
47227db96d56Sopenharmony_ci    Py_DECREF(seq);
47237db96d56Sopenharmony_ci
47247db96d56Sopenharmony_ciDone:
47257db96d56Sopenharmony_ci    Py_ReprLeave((PyObject *)dv);
47267db96d56Sopenharmony_ci    return result;
47277db96d56Sopenharmony_ci}
47287db96d56Sopenharmony_ci
47297db96d56Sopenharmony_ci/*** dict_keys ***/
47307db96d56Sopenharmony_ci
47317db96d56Sopenharmony_cistatic PyObject *
47327db96d56Sopenharmony_cidictkeys_iter(_PyDictViewObject *dv)
47337db96d56Sopenharmony_ci{
47347db96d56Sopenharmony_ci    if (dv->dv_dict == NULL) {
47357db96d56Sopenharmony_ci        Py_RETURN_NONE;
47367db96d56Sopenharmony_ci    }
47377db96d56Sopenharmony_ci    return dictiter_new(dv->dv_dict, &PyDictIterKey_Type);
47387db96d56Sopenharmony_ci}
47397db96d56Sopenharmony_ci
47407db96d56Sopenharmony_cistatic int
47417db96d56Sopenharmony_cidictkeys_contains(_PyDictViewObject *dv, PyObject *obj)
47427db96d56Sopenharmony_ci{
47437db96d56Sopenharmony_ci    if (dv->dv_dict == NULL)
47447db96d56Sopenharmony_ci        return 0;
47457db96d56Sopenharmony_ci    return PyDict_Contains((PyObject *)dv->dv_dict, obj);
47467db96d56Sopenharmony_ci}
47477db96d56Sopenharmony_ci
47487db96d56Sopenharmony_cistatic PySequenceMethods dictkeys_as_sequence = {
47497db96d56Sopenharmony_ci    (lenfunc)dictview_len,              /* sq_length */
47507db96d56Sopenharmony_ci    0,                                  /* sq_concat */
47517db96d56Sopenharmony_ci    0,                                  /* sq_repeat */
47527db96d56Sopenharmony_ci    0,                                  /* sq_item */
47537db96d56Sopenharmony_ci    0,                                  /* sq_slice */
47547db96d56Sopenharmony_ci    0,                                  /* sq_ass_item */
47557db96d56Sopenharmony_ci    0,                                  /* sq_ass_slice */
47567db96d56Sopenharmony_ci    (objobjproc)dictkeys_contains,      /* sq_contains */
47577db96d56Sopenharmony_ci};
47587db96d56Sopenharmony_ci
47597db96d56Sopenharmony_ci// Create an set object from dictviews object.
47607db96d56Sopenharmony_ci// Returns a new reference.
47617db96d56Sopenharmony_ci// This utility function is used by set operations.
47627db96d56Sopenharmony_cistatic PyObject*
47637db96d56Sopenharmony_cidictviews_to_set(PyObject *self)
47647db96d56Sopenharmony_ci{
47657db96d56Sopenharmony_ci    PyObject *left = self;
47667db96d56Sopenharmony_ci    if (PyDictKeys_Check(self)) {
47677db96d56Sopenharmony_ci        // PySet_New() has fast path for the dict object.
47687db96d56Sopenharmony_ci        PyObject *dict = (PyObject *)((_PyDictViewObject *)self)->dv_dict;
47697db96d56Sopenharmony_ci        if (PyDict_CheckExact(dict)) {
47707db96d56Sopenharmony_ci            left = dict;
47717db96d56Sopenharmony_ci        }
47727db96d56Sopenharmony_ci    }
47737db96d56Sopenharmony_ci    return PySet_New(left);
47747db96d56Sopenharmony_ci}
47757db96d56Sopenharmony_ci
47767db96d56Sopenharmony_cistatic PyObject*
47777db96d56Sopenharmony_cidictviews_sub(PyObject *self, PyObject *other)
47787db96d56Sopenharmony_ci{
47797db96d56Sopenharmony_ci    PyObject *result = dictviews_to_set(self);
47807db96d56Sopenharmony_ci    if (result == NULL) {
47817db96d56Sopenharmony_ci        return NULL;
47827db96d56Sopenharmony_ci    }
47837db96d56Sopenharmony_ci
47847db96d56Sopenharmony_ci    PyObject *tmp = PyObject_CallMethodOneArg(
47857db96d56Sopenharmony_ci            result, &_Py_ID(difference_update), other);
47867db96d56Sopenharmony_ci    if (tmp == NULL) {
47877db96d56Sopenharmony_ci        Py_DECREF(result);
47887db96d56Sopenharmony_ci        return NULL;
47897db96d56Sopenharmony_ci    }
47907db96d56Sopenharmony_ci
47917db96d56Sopenharmony_ci    Py_DECREF(tmp);
47927db96d56Sopenharmony_ci    return result;
47937db96d56Sopenharmony_ci}
47947db96d56Sopenharmony_ci
47957db96d56Sopenharmony_cistatic int
47967db96d56Sopenharmony_cidictitems_contains(_PyDictViewObject *dv, PyObject *obj);
47977db96d56Sopenharmony_ci
47987db96d56Sopenharmony_ciPyObject *
47997db96d56Sopenharmony_ci_PyDictView_Intersect(PyObject* self, PyObject *other)
48007db96d56Sopenharmony_ci{
48017db96d56Sopenharmony_ci    PyObject *result;
48027db96d56Sopenharmony_ci    PyObject *it;
48037db96d56Sopenharmony_ci    PyObject *key;
48047db96d56Sopenharmony_ci    Py_ssize_t len_self;
48057db96d56Sopenharmony_ci    int rv;
48067db96d56Sopenharmony_ci    int (*dict_contains)(_PyDictViewObject *, PyObject *);
48077db96d56Sopenharmony_ci
48087db96d56Sopenharmony_ci    /* Python interpreter swaps parameters when dict view
48097db96d56Sopenharmony_ci       is on right side of & */
48107db96d56Sopenharmony_ci    if (!PyDictViewSet_Check(self)) {
48117db96d56Sopenharmony_ci        PyObject *tmp = other;
48127db96d56Sopenharmony_ci        other = self;
48137db96d56Sopenharmony_ci        self = tmp;
48147db96d56Sopenharmony_ci    }
48157db96d56Sopenharmony_ci
48167db96d56Sopenharmony_ci    len_self = dictview_len((_PyDictViewObject *)self);
48177db96d56Sopenharmony_ci
48187db96d56Sopenharmony_ci    /* if other is a set and self is smaller than other,
48197db96d56Sopenharmony_ci       reuse set intersection logic */
48207db96d56Sopenharmony_ci    if (PySet_CheckExact(other) && len_self <= PyObject_Size(other)) {
48217db96d56Sopenharmony_ci        return PyObject_CallMethodObjArgs(
48227db96d56Sopenharmony_ci                other, &_Py_ID(intersection), self, NULL);
48237db96d56Sopenharmony_ci    }
48247db96d56Sopenharmony_ci
48257db96d56Sopenharmony_ci    /* if other is another dict view, and it is bigger than self,
48267db96d56Sopenharmony_ci       swap them */
48277db96d56Sopenharmony_ci    if (PyDictViewSet_Check(other)) {
48287db96d56Sopenharmony_ci        Py_ssize_t len_other = dictview_len((_PyDictViewObject *)other);
48297db96d56Sopenharmony_ci        if (len_other > len_self) {
48307db96d56Sopenharmony_ci            PyObject *tmp = other;
48317db96d56Sopenharmony_ci            other = self;
48327db96d56Sopenharmony_ci            self = tmp;
48337db96d56Sopenharmony_ci        }
48347db96d56Sopenharmony_ci    }
48357db96d56Sopenharmony_ci
48367db96d56Sopenharmony_ci    /* at this point, two things should be true
48377db96d56Sopenharmony_ci       1. self is a dictview
48387db96d56Sopenharmony_ci       2. if other is a dictview then it is smaller than self */
48397db96d56Sopenharmony_ci    result = PySet_New(NULL);
48407db96d56Sopenharmony_ci    if (result == NULL)
48417db96d56Sopenharmony_ci        return NULL;
48427db96d56Sopenharmony_ci
48437db96d56Sopenharmony_ci    it = PyObject_GetIter(other);
48447db96d56Sopenharmony_ci    if (it == NULL) {
48457db96d56Sopenharmony_ci        Py_DECREF(result);
48467db96d56Sopenharmony_ci        return NULL;
48477db96d56Sopenharmony_ci    }
48487db96d56Sopenharmony_ci
48497db96d56Sopenharmony_ci    if (PyDictKeys_Check(self)) {
48507db96d56Sopenharmony_ci        dict_contains = dictkeys_contains;
48517db96d56Sopenharmony_ci    }
48527db96d56Sopenharmony_ci    /* else PyDictItems_Check(self) */
48537db96d56Sopenharmony_ci    else {
48547db96d56Sopenharmony_ci        dict_contains = dictitems_contains;
48557db96d56Sopenharmony_ci    }
48567db96d56Sopenharmony_ci
48577db96d56Sopenharmony_ci    while ((key = PyIter_Next(it)) != NULL) {
48587db96d56Sopenharmony_ci        rv = dict_contains((_PyDictViewObject *)self, key);
48597db96d56Sopenharmony_ci        if (rv < 0) {
48607db96d56Sopenharmony_ci            goto error;
48617db96d56Sopenharmony_ci        }
48627db96d56Sopenharmony_ci        if (rv) {
48637db96d56Sopenharmony_ci            if (PySet_Add(result, key)) {
48647db96d56Sopenharmony_ci                goto error;
48657db96d56Sopenharmony_ci            }
48667db96d56Sopenharmony_ci        }
48677db96d56Sopenharmony_ci        Py_DECREF(key);
48687db96d56Sopenharmony_ci    }
48697db96d56Sopenharmony_ci    Py_DECREF(it);
48707db96d56Sopenharmony_ci    if (PyErr_Occurred()) {
48717db96d56Sopenharmony_ci        Py_DECREF(result);
48727db96d56Sopenharmony_ci        return NULL;
48737db96d56Sopenharmony_ci    }
48747db96d56Sopenharmony_ci    return result;
48757db96d56Sopenharmony_ci
48767db96d56Sopenharmony_cierror:
48777db96d56Sopenharmony_ci    Py_DECREF(it);
48787db96d56Sopenharmony_ci    Py_DECREF(result);
48797db96d56Sopenharmony_ci    Py_DECREF(key);
48807db96d56Sopenharmony_ci    return NULL;
48817db96d56Sopenharmony_ci}
48827db96d56Sopenharmony_ci
48837db96d56Sopenharmony_cistatic PyObject*
48847db96d56Sopenharmony_cidictviews_or(PyObject* self, PyObject *other)
48857db96d56Sopenharmony_ci{
48867db96d56Sopenharmony_ci    PyObject *result = dictviews_to_set(self);
48877db96d56Sopenharmony_ci    if (result == NULL) {
48887db96d56Sopenharmony_ci        return NULL;
48897db96d56Sopenharmony_ci    }
48907db96d56Sopenharmony_ci
48917db96d56Sopenharmony_ci    if (_PySet_Update(result, other) < 0) {
48927db96d56Sopenharmony_ci        Py_DECREF(result);
48937db96d56Sopenharmony_ci        return NULL;
48947db96d56Sopenharmony_ci    }
48957db96d56Sopenharmony_ci    return result;
48967db96d56Sopenharmony_ci}
48977db96d56Sopenharmony_ci
48987db96d56Sopenharmony_cistatic PyObject *
48997db96d56Sopenharmony_cidictitems_xor(PyObject *self, PyObject *other)
49007db96d56Sopenharmony_ci{
49017db96d56Sopenharmony_ci    assert(PyDictItems_Check(self));
49027db96d56Sopenharmony_ci    assert(PyDictItems_Check(other));
49037db96d56Sopenharmony_ci    PyObject *d1 = (PyObject *)((_PyDictViewObject *)self)->dv_dict;
49047db96d56Sopenharmony_ci    PyObject *d2 = (PyObject *)((_PyDictViewObject *)other)->dv_dict;
49057db96d56Sopenharmony_ci
49067db96d56Sopenharmony_ci    PyObject *temp_dict = PyDict_Copy(d1);
49077db96d56Sopenharmony_ci    if (temp_dict == NULL) {
49087db96d56Sopenharmony_ci        return NULL;
49097db96d56Sopenharmony_ci    }
49107db96d56Sopenharmony_ci    PyObject *result_set = PySet_New(NULL);
49117db96d56Sopenharmony_ci    if (result_set == NULL) {
49127db96d56Sopenharmony_ci        Py_CLEAR(temp_dict);
49137db96d56Sopenharmony_ci        return NULL;
49147db96d56Sopenharmony_ci    }
49157db96d56Sopenharmony_ci
49167db96d56Sopenharmony_ci    PyObject *key = NULL, *val1 = NULL, *val2 = NULL;
49177db96d56Sopenharmony_ci    Py_ssize_t pos = 0;
49187db96d56Sopenharmony_ci    Py_hash_t hash;
49197db96d56Sopenharmony_ci
49207db96d56Sopenharmony_ci    while (_PyDict_Next(d2, &pos, &key, &val2, &hash)) {
49217db96d56Sopenharmony_ci        Py_INCREF(key);
49227db96d56Sopenharmony_ci        Py_INCREF(val2);
49237db96d56Sopenharmony_ci        val1 = _PyDict_GetItem_KnownHash(temp_dict, key, hash);
49247db96d56Sopenharmony_ci
49257db96d56Sopenharmony_ci        int to_delete;
49267db96d56Sopenharmony_ci        if (val1 == NULL) {
49277db96d56Sopenharmony_ci            if (PyErr_Occurred()) {
49287db96d56Sopenharmony_ci                goto error;
49297db96d56Sopenharmony_ci            }
49307db96d56Sopenharmony_ci            to_delete = 0;
49317db96d56Sopenharmony_ci        }
49327db96d56Sopenharmony_ci        else {
49337db96d56Sopenharmony_ci            Py_INCREF(val1);
49347db96d56Sopenharmony_ci            to_delete = PyObject_RichCompareBool(val1, val2, Py_EQ);
49357db96d56Sopenharmony_ci            if (to_delete < 0) {
49367db96d56Sopenharmony_ci                goto error;
49377db96d56Sopenharmony_ci            }
49387db96d56Sopenharmony_ci        }
49397db96d56Sopenharmony_ci
49407db96d56Sopenharmony_ci        if (to_delete) {
49417db96d56Sopenharmony_ci            if (_PyDict_DelItem_KnownHash(temp_dict, key, hash) < 0) {
49427db96d56Sopenharmony_ci                goto error;
49437db96d56Sopenharmony_ci            }
49447db96d56Sopenharmony_ci        }
49457db96d56Sopenharmony_ci        else {
49467db96d56Sopenharmony_ci            PyObject *pair = PyTuple_Pack(2, key, val2);
49477db96d56Sopenharmony_ci            if (pair == NULL) {
49487db96d56Sopenharmony_ci                goto error;
49497db96d56Sopenharmony_ci            }
49507db96d56Sopenharmony_ci            if (PySet_Add(result_set, pair) < 0) {
49517db96d56Sopenharmony_ci                Py_DECREF(pair);
49527db96d56Sopenharmony_ci                goto error;
49537db96d56Sopenharmony_ci            }
49547db96d56Sopenharmony_ci            Py_DECREF(pair);
49557db96d56Sopenharmony_ci        }
49567db96d56Sopenharmony_ci        Py_DECREF(key);
49577db96d56Sopenharmony_ci        Py_XDECREF(val1);
49587db96d56Sopenharmony_ci        Py_DECREF(val2);
49597db96d56Sopenharmony_ci    }
49607db96d56Sopenharmony_ci    key = val1 = val2 = NULL;
49617db96d56Sopenharmony_ci
49627db96d56Sopenharmony_ci    PyObject *remaining_pairs = PyObject_CallMethodNoArgs(
49637db96d56Sopenharmony_ci            temp_dict, &_Py_ID(items));
49647db96d56Sopenharmony_ci    if (remaining_pairs == NULL) {
49657db96d56Sopenharmony_ci        goto error;
49667db96d56Sopenharmony_ci    }
49677db96d56Sopenharmony_ci    if (_PySet_Update(result_set, remaining_pairs) < 0) {
49687db96d56Sopenharmony_ci        Py_DECREF(remaining_pairs);
49697db96d56Sopenharmony_ci        goto error;
49707db96d56Sopenharmony_ci    }
49717db96d56Sopenharmony_ci    Py_DECREF(temp_dict);
49727db96d56Sopenharmony_ci    Py_DECREF(remaining_pairs);
49737db96d56Sopenharmony_ci    return result_set;
49747db96d56Sopenharmony_ci
49757db96d56Sopenharmony_cierror:
49767db96d56Sopenharmony_ci    Py_XDECREF(temp_dict);
49777db96d56Sopenharmony_ci    Py_XDECREF(result_set);
49787db96d56Sopenharmony_ci    Py_XDECREF(key);
49797db96d56Sopenharmony_ci    Py_XDECREF(val1);
49807db96d56Sopenharmony_ci    Py_XDECREF(val2);
49817db96d56Sopenharmony_ci    return NULL;
49827db96d56Sopenharmony_ci}
49837db96d56Sopenharmony_ci
49847db96d56Sopenharmony_cistatic PyObject*
49857db96d56Sopenharmony_cidictviews_xor(PyObject* self, PyObject *other)
49867db96d56Sopenharmony_ci{
49877db96d56Sopenharmony_ci    if (PyDictItems_Check(self) && PyDictItems_Check(other)) {
49887db96d56Sopenharmony_ci        return dictitems_xor(self, other);
49897db96d56Sopenharmony_ci    }
49907db96d56Sopenharmony_ci    PyObject *result = dictviews_to_set(self);
49917db96d56Sopenharmony_ci    if (result == NULL) {
49927db96d56Sopenharmony_ci        return NULL;
49937db96d56Sopenharmony_ci    }
49947db96d56Sopenharmony_ci
49957db96d56Sopenharmony_ci    PyObject *tmp = PyObject_CallMethodOneArg(
49967db96d56Sopenharmony_ci            result, &_Py_ID(symmetric_difference_update), other);
49977db96d56Sopenharmony_ci    if (tmp == NULL) {
49987db96d56Sopenharmony_ci        Py_DECREF(result);
49997db96d56Sopenharmony_ci        return NULL;
50007db96d56Sopenharmony_ci    }
50017db96d56Sopenharmony_ci
50027db96d56Sopenharmony_ci    Py_DECREF(tmp);
50037db96d56Sopenharmony_ci    return result;
50047db96d56Sopenharmony_ci}
50057db96d56Sopenharmony_ci
50067db96d56Sopenharmony_cistatic PyNumberMethods dictviews_as_number = {
50077db96d56Sopenharmony_ci    0,                                  /*nb_add*/
50087db96d56Sopenharmony_ci    (binaryfunc)dictviews_sub,          /*nb_subtract*/
50097db96d56Sopenharmony_ci    0,                                  /*nb_multiply*/
50107db96d56Sopenharmony_ci    0,                                  /*nb_remainder*/
50117db96d56Sopenharmony_ci    0,                                  /*nb_divmod*/
50127db96d56Sopenharmony_ci    0,                                  /*nb_power*/
50137db96d56Sopenharmony_ci    0,                                  /*nb_negative*/
50147db96d56Sopenharmony_ci    0,                                  /*nb_positive*/
50157db96d56Sopenharmony_ci    0,                                  /*nb_absolute*/
50167db96d56Sopenharmony_ci    0,                                  /*nb_bool*/
50177db96d56Sopenharmony_ci    0,                                  /*nb_invert*/
50187db96d56Sopenharmony_ci    0,                                  /*nb_lshift*/
50197db96d56Sopenharmony_ci    0,                                  /*nb_rshift*/
50207db96d56Sopenharmony_ci    (binaryfunc)_PyDictView_Intersect,  /*nb_and*/
50217db96d56Sopenharmony_ci    (binaryfunc)dictviews_xor,          /*nb_xor*/
50227db96d56Sopenharmony_ci    (binaryfunc)dictviews_or,           /*nb_or*/
50237db96d56Sopenharmony_ci};
50247db96d56Sopenharmony_ci
50257db96d56Sopenharmony_cistatic PyObject*
50267db96d56Sopenharmony_cidictviews_isdisjoint(PyObject *self, PyObject *other)
50277db96d56Sopenharmony_ci{
50287db96d56Sopenharmony_ci    PyObject *it;
50297db96d56Sopenharmony_ci    PyObject *item = NULL;
50307db96d56Sopenharmony_ci
50317db96d56Sopenharmony_ci    if (self == other) {
50327db96d56Sopenharmony_ci        if (dictview_len((_PyDictViewObject *)self) == 0)
50337db96d56Sopenharmony_ci            Py_RETURN_TRUE;
50347db96d56Sopenharmony_ci        else
50357db96d56Sopenharmony_ci            Py_RETURN_FALSE;
50367db96d56Sopenharmony_ci    }
50377db96d56Sopenharmony_ci
50387db96d56Sopenharmony_ci    /* Iterate over the shorter object (only if other is a set,
50397db96d56Sopenharmony_ci     * because PySequence_Contains may be expensive otherwise): */
50407db96d56Sopenharmony_ci    if (PyAnySet_Check(other) || PyDictViewSet_Check(other)) {
50417db96d56Sopenharmony_ci        Py_ssize_t len_self = dictview_len((_PyDictViewObject *)self);
50427db96d56Sopenharmony_ci        Py_ssize_t len_other = PyObject_Size(other);
50437db96d56Sopenharmony_ci        if (len_other == -1)
50447db96d56Sopenharmony_ci            return NULL;
50457db96d56Sopenharmony_ci
50467db96d56Sopenharmony_ci        if ((len_other > len_self)) {
50477db96d56Sopenharmony_ci            PyObject *tmp = other;
50487db96d56Sopenharmony_ci            other = self;
50497db96d56Sopenharmony_ci            self = tmp;
50507db96d56Sopenharmony_ci        }
50517db96d56Sopenharmony_ci    }
50527db96d56Sopenharmony_ci
50537db96d56Sopenharmony_ci    it = PyObject_GetIter(other);
50547db96d56Sopenharmony_ci    if (it == NULL)
50557db96d56Sopenharmony_ci        return NULL;
50567db96d56Sopenharmony_ci
50577db96d56Sopenharmony_ci    while ((item = PyIter_Next(it)) != NULL) {
50587db96d56Sopenharmony_ci        int contains = PySequence_Contains(self, item);
50597db96d56Sopenharmony_ci        Py_DECREF(item);
50607db96d56Sopenharmony_ci        if (contains == -1) {
50617db96d56Sopenharmony_ci            Py_DECREF(it);
50627db96d56Sopenharmony_ci            return NULL;
50637db96d56Sopenharmony_ci        }
50647db96d56Sopenharmony_ci
50657db96d56Sopenharmony_ci        if (contains) {
50667db96d56Sopenharmony_ci            Py_DECREF(it);
50677db96d56Sopenharmony_ci            Py_RETURN_FALSE;
50687db96d56Sopenharmony_ci        }
50697db96d56Sopenharmony_ci    }
50707db96d56Sopenharmony_ci    Py_DECREF(it);
50717db96d56Sopenharmony_ci    if (PyErr_Occurred())
50727db96d56Sopenharmony_ci        return NULL; /* PyIter_Next raised an exception. */
50737db96d56Sopenharmony_ci    Py_RETURN_TRUE;
50747db96d56Sopenharmony_ci}
50757db96d56Sopenharmony_ci
50767db96d56Sopenharmony_ciPyDoc_STRVAR(isdisjoint_doc,
50777db96d56Sopenharmony_ci"Return True if the view and the given iterable have a null intersection.");
50787db96d56Sopenharmony_ci
50797db96d56Sopenharmony_cistatic PyObject* dictkeys_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored));
50807db96d56Sopenharmony_ci
50817db96d56Sopenharmony_ciPyDoc_STRVAR(reversed_keys_doc,
50827db96d56Sopenharmony_ci"Return a reverse iterator over the dict keys.");
50837db96d56Sopenharmony_ci
50847db96d56Sopenharmony_cistatic PyMethodDef dictkeys_methods[] = {
50857db96d56Sopenharmony_ci    {"isdisjoint",      (PyCFunction)dictviews_isdisjoint,  METH_O,
50867db96d56Sopenharmony_ci     isdisjoint_doc},
50877db96d56Sopenharmony_ci    {"__reversed__",    _PyCFunction_CAST(dictkeys_reversed),    METH_NOARGS,
50887db96d56Sopenharmony_ci     reversed_keys_doc},
50897db96d56Sopenharmony_ci    {NULL,              NULL}           /* sentinel */
50907db96d56Sopenharmony_ci};
50917db96d56Sopenharmony_ci
50927db96d56Sopenharmony_ciPyTypeObject PyDictKeys_Type = {
50937db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
50947db96d56Sopenharmony_ci    "dict_keys",                                /* tp_name */
50957db96d56Sopenharmony_ci    sizeof(_PyDictViewObject),                  /* tp_basicsize */
50967db96d56Sopenharmony_ci    0,                                          /* tp_itemsize */
50977db96d56Sopenharmony_ci    /* methods */
50987db96d56Sopenharmony_ci    (destructor)dictview_dealloc,               /* tp_dealloc */
50997db96d56Sopenharmony_ci    0,                                          /* tp_vectorcall_offset */
51007db96d56Sopenharmony_ci    0,                                          /* tp_getattr */
51017db96d56Sopenharmony_ci    0,                                          /* tp_setattr */
51027db96d56Sopenharmony_ci    0,                                          /* tp_as_async */
51037db96d56Sopenharmony_ci    (reprfunc)dictview_repr,                    /* tp_repr */
51047db96d56Sopenharmony_ci    &dictviews_as_number,                       /* tp_as_number */
51057db96d56Sopenharmony_ci    &dictkeys_as_sequence,                      /* tp_as_sequence */
51067db96d56Sopenharmony_ci    0,                                          /* tp_as_mapping */
51077db96d56Sopenharmony_ci    0,                                          /* tp_hash */
51087db96d56Sopenharmony_ci    0,                                          /* tp_call */
51097db96d56Sopenharmony_ci    0,                                          /* tp_str */
51107db96d56Sopenharmony_ci    PyObject_GenericGetAttr,                    /* tp_getattro */
51117db96d56Sopenharmony_ci    0,                                          /* tp_setattro */
51127db96d56Sopenharmony_ci    0,                                          /* tp_as_buffer */
51137db96d56Sopenharmony_ci    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
51147db96d56Sopenharmony_ci    0,                                          /* tp_doc */
51157db96d56Sopenharmony_ci    (traverseproc)dictview_traverse,            /* tp_traverse */
51167db96d56Sopenharmony_ci    0,                                          /* tp_clear */
51177db96d56Sopenharmony_ci    dictview_richcompare,                       /* tp_richcompare */
51187db96d56Sopenharmony_ci    0,                                          /* tp_weaklistoffset */
51197db96d56Sopenharmony_ci    (getiterfunc)dictkeys_iter,                 /* tp_iter */
51207db96d56Sopenharmony_ci    0,                                          /* tp_iternext */
51217db96d56Sopenharmony_ci    dictkeys_methods,                           /* tp_methods */
51227db96d56Sopenharmony_ci    .tp_getset = dictview_getset,
51237db96d56Sopenharmony_ci};
51247db96d56Sopenharmony_ci
51257db96d56Sopenharmony_cistatic PyObject *
51267db96d56Sopenharmony_cidictkeys_new(PyObject *dict, PyObject *Py_UNUSED(ignored))
51277db96d56Sopenharmony_ci{
51287db96d56Sopenharmony_ci    return _PyDictView_New(dict, &PyDictKeys_Type);
51297db96d56Sopenharmony_ci}
51307db96d56Sopenharmony_ci
51317db96d56Sopenharmony_cistatic PyObject *
51327db96d56Sopenharmony_cidictkeys_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
51337db96d56Sopenharmony_ci{
51347db96d56Sopenharmony_ci    if (dv->dv_dict == NULL) {
51357db96d56Sopenharmony_ci        Py_RETURN_NONE;
51367db96d56Sopenharmony_ci    }
51377db96d56Sopenharmony_ci    return dictiter_new(dv->dv_dict, &PyDictRevIterKey_Type);
51387db96d56Sopenharmony_ci}
51397db96d56Sopenharmony_ci
51407db96d56Sopenharmony_ci/*** dict_items ***/
51417db96d56Sopenharmony_ci
51427db96d56Sopenharmony_cistatic PyObject *
51437db96d56Sopenharmony_cidictitems_iter(_PyDictViewObject *dv)
51447db96d56Sopenharmony_ci{
51457db96d56Sopenharmony_ci    if (dv->dv_dict == NULL) {
51467db96d56Sopenharmony_ci        Py_RETURN_NONE;
51477db96d56Sopenharmony_ci    }
51487db96d56Sopenharmony_ci    return dictiter_new(dv->dv_dict, &PyDictIterItem_Type);
51497db96d56Sopenharmony_ci}
51507db96d56Sopenharmony_ci
51517db96d56Sopenharmony_cistatic int
51527db96d56Sopenharmony_cidictitems_contains(_PyDictViewObject *dv, PyObject *obj)
51537db96d56Sopenharmony_ci{
51547db96d56Sopenharmony_ci    int result;
51557db96d56Sopenharmony_ci    PyObject *key, *value, *found;
51567db96d56Sopenharmony_ci    if (dv->dv_dict == NULL)
51577db96d56Sopenharmony_ci        return 0;
51587db96d56Sopenharmony_ci    if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 2)
51597db96d56Sopenharmony_ci        return 0;
51607db96d56Sopenharmony_ci    key = PyTuple_GET_ITEM(obj, 0);
51617db96d56Sopenharmony_ci    value = PyTuple_GET_ITEM(obj, 1);
51627db96d56Sopenharmony_ci    found = PyDict_GetItemWithError((PyObject *)dv->dv_dict, key);
51637db96d56Sopenharmony_ci    if (found == NULL) {
51647db96d56Sopenharmony_ci        if (PyErr_Occurred())
51657db96d56Sopenharmony_ci            return -1;
51667db96d56Sopenharmony_ci        return 0;
51677db96d56Sopenharmony_ci    }
51687db96d56Sopenharmony_ci    Py_INCREF(found);
51697db96d56Sopenharmony_ci    result = PyObject_RichCompareBool(found, value, Py_EQ);
51707db96d56Sopenharmony_ci    Py_DECREF(found);
51717db96d56Sopenharmony_ci    return result;
51727db96d56Sopenharmony_ci}
51737db96d56Sopenharmony_ci
51747db96d56Sopenharmony_cistatic PySequenceMethods dictitems_as_sequence = {
51757db96d56Sopenharmony_ci    (lenfunc)dictview_len,              /* sq_length */
51767db96d56Sopenharmony_ci    0,                                  /* sq_concat */
51777db96d56Sopenharmony_ci    0,                                  /* sq_repeat */
51787db96d56Sopenharmony_ci    0,                                  /* sq_item */
51797db96d56Sopenharmony_ci    0,                                  /* sq_slice */
51807db96d56Sopenharmony_ci    0,                                  /* sq_ass_item */
51817db96d56Sopenharmony_ci    0,                                  /* sq_ass_slice */
51827db96d56Sopenharmony_ci    (objobjproc)dictitems_contains,     /* sq_contains */
51837db96d56Sopenharmony_ci};
51847db96d56Sopenharmony_ci
51857db96d56Sopenharmony_cistatic PyObject* dictitems_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored));
51867db96d56Sopenharmony_ci
51877db96d56Sopenharmony_ciPyDoc_STRVAR(reversed_items_doc,
51887db96d56Sopenharmony_ci"Return a reverse iterator over the dict items.");
51897db96d56Sopenharmony_ci
51907db96d56Sopenharmony_cistatic PyMethodDef dictitems_methods[] = {
51917db96d56Sopenharmony_ci    {"isdisjoint",      (PyCFunction)dictviews_isdisjoint,  METH_O,
51927db96d56Sopenharmony_ci     isdisjoint_doc},
51937db96d56Sopenharmony_ci    {"__reversed__",    (PyCFunction)dictitems_reversed,    METH_NOARGS,
51947db96d56Sopenharmony_ci     reversed_items_doc},
51957db96d56Sopenharmony_ci    {NULL,              NULL}           /* sentinel */
51967db96d56Sopenharmony_ci};
51977db96d56Sopenharmony_ci
51987db96d56Sopenharmony_ciPyTypeObject PyDictItems_Type = {
51997db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
52007db96d56Sopenharmony_ci    "dict_items",                               /* tp_name */
52017db96d56Sopenharmony_ci    sizeof(_PyDictViewObject),                  /* tp_basicsize */
52027db96d56Sopenharmony_ci    0,                                          /* tp_itemsize */
52037db96d56Sopenharmony_ci    /* methods */
52047db96d56Sopenharmony_ci    (destructor)dictview_dealloc,               /* tp_dealloc */
52057db96d56Sopenharmony_ci    0,                                          /* tp_vectorcall_offset */
52067db96d56Sopenharmony_ci    0,                                          /* tp_getattr */
52077db96d56Sopenharmony_ci    0,                                          /* tp_setattr */
52087db96d56Sopenharmony_ci    0,                                          /* tp_as_async */
52097db96d56Sopenharmony_ci    (reprfunc)dictview_repr,                    /* tp_repr */
52107db96d56Sopenharmony_ci    &dictviews_as_number,                       /* tp_as_number */
52117db96d56Sopenharmony_ci    &dictitems_as_sequence,                     /* tp_as_sequence */
52127db96d56Sopenharmony_ci    0,                                          /* tp_as_mapping */
52137db96d56Sopenharmony_ci    0,                                          /* tp_hash */
52147db96d56Sopenharmony_ci    0,                                          /* tp_call */
52157db96d56Sopenharmony_ci    0,                                          /* tp_str */
52167db96d56Sopenharmony_ci    PyObject_GenericGetAttr,                    /* tp_getattro */
52177db96d56Sopenharmony_ci    0,                                          /* tp_setattro */
52187db96d56Sopenharmony_ci    0,                                          /* tp_as_buffer */
52197db96d56Sopenharmony_ci    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
52207db96d56Sopenharmony_ci    0,                                          /* tp_doc */
52217db96d56Sopenharmony_ci    (traverseproc)dictview_traverse,            /* tp_traverse */
52227db96d56Sopenharmony_ci    0,                                          /* tp_clear */
52237db96d56Sopenharmony_ci    dictview_richcompare,                       /* tp_richcompare */
52247db96d56Sopenharmony_ci    0,                                          /* tp_weaklistoffset */
52257db96d56Sopenharmony_ci    (getiterfunc)dictitems_iter,                /* tp_iter */
52267db96d56Sopenharmony_ci    0,                                          /* tp_iternext */
52277db96d56Sopenharmony_ci    dictitems_methods,                          /* tp_methods */
52287db96d56Sopenharmony_ci    .tp_getset = dictview_getset,
52297db96d56Sopenharmony_ci};
52307db96d56Sopenharmony_ci
52317db96d56Sopenharmony_cistatic PyObject *
52327db96d56Sopenharmony_cidictitems_new(PyObject *dict, PyObject *Py_UNUSED(ignored))
52337db96d56Sopenharmony_ci{
52347db96d56Sopenharmony_ci    return _PyDictView_New(dict, &PyDictItems_Type);
52357db96d56Sopenharmony_ci}
52367db96d56Sopenharmony_ci
52377db96d56Sopenharmony_cistatic PyObject *
52387db96d56Sopenharmony_cidictitems_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
52397db96d56Sopenharmony_ci{
52407db96d56Sopenharmony_ci    if (dv->dv_dict == NULL) {
52417db96d56Sopenharmony_ci        Py_RETURN_NONE;
52427db96d56Sopenharmony_ci    }
52437db96d56Sopenharmony_ci    return dictiter_new(dv->dv_dict, &PyDictRevIterItem_Type);
52447db96d56Sopenharmony_ci}
52457db96d56Sopenharmony_ci
52467db96d56Sopenharmony_ci/*** dict_values ***/
52477db96d56Sopenharmony_ci
52487db96d56Sopenharmony_cistatic PyObject *
52497db96d56Sopenharmony_cidictvalues_iter(_PyDictViewObject *dv)
52507db96d56Sopenharmony_ci{
52517db96d56Sopenharmony_ci    if (dv->dv_dict == NULL) {
52527db96d56Sopenharmony_ci        Py_RETURN_NONE;
52537db96d56Sopenharmony_ci    }
52547db96d56Sopenharmony_ci    return dictiter_new(dv->dv_dict, &PyDictIterValue_Type);
52557db96d56Sopenharmony_ci}
52567db96d56Sopenharmony_ci
52577db96d56Sopenharmony_cistatic PySequenceMethods dictvalues_as_sequence = {
52587db96d56Sopenharmony_ci    (lenfunc)dictview_len,              /* sq_length */
52597db96d56Sopenharmony_ci    0,                                  /* sq_concat */
52607db96d56Sopenharmony_ci    0,                                  /* sq_repeat */
52617db96d56Sopenharmony_ci    0,                                  /* sq_item */
52627db96d56Sopenharmony_ci    0,                                  /* sq_slice */
52637db96d56Sopenharmony_ci    0,                                  /* sq_ass_item */
52647db96d56Sopenharmony_ci    0,                                  /* sq_ass_slice */
52657db96d56Sopenharmony_ci    (objobjproc)0,                      /* sq_contains */
52667db96d56Sopenharmony_ci};
52677db96d56Sopenharmony_ci
52687db96d56Sopenharmony_cistatic PyObject* dictvalues_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored));
52697db96d56Sopenharmony_ci
52707db96d56Sopenharmony_ciPyDoc_STRVAR(reversed_values_doc,
52717db96d56Sopenharmony_ci"Return a reverse iterator over the dict values.");
52727db96d56Sopenharmony_ci
52737db96d56Sopenharmony_cistatic PyMethodDef dictvalues_methods[] = {
52747db96d56Sopenharmony_ci    {"__reversed__",    (PyCFunction)dictvalues_reversed,    METH_NOARGS,
52757db96d56Sopenharmony_ci     reversed_values_doc},
52767db96d56Sopenharmony_ci    {NULL,              NULL}           /* sentinel */
52777db96d56Sopenharmony_ci};
52787db96d56Sopenharmony_ci
52797db96d56Sopenharmony_ciPyTypeObject PyDictValues_Type = {
52807db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
52817db96d56Sopenharmony_ci    "dict_values",                              /* tp_name */
52827db96d56Sopenharmony_ci    sizeof(_PyDictViewObject),                  /* tp_basicsize */
52837db96d56Sopenharmony_ci    0,                                          /* tp_itemsize */
52847db96d56Sopenharmony_ci    /* methods */
52857db96d56Sopenharmony_ci    (destructor)dictview_dealloc,               /* tp_dealloc */
52867db96d56Sopenharmony_ci    0,                                          /* tp_vectorcall_offset */
52877db96d56Sopenharmony_ci    0,                                          /* tp_getattr */
52887db96d56Sopenharmony_ci    0,                                          /* tp_setattr */
52897db96d56Sopenharmony_ci    0,                                          /* tp_as_async */
52907db96d56Sopenharmony_ci    (reprfunc)dictview_repr,                    /* tp_repr */
52917db96d56Sopenharmony_ci    0,                                          /* tp_as_number */
52927db96d56Sopenharmony_ci    &dictvalues_as_sequence,                    /* tp_as_sequence */
52937db96d56Sopenharmony_ci    0,                                          /* tp_as_mapping */
52947db96d56Sopenharmony_ci    0,                                          /* tp_hash */
52957db96d56Sopenharmony_ci    0,                                          /* tp_call */
52967db96d56Sopenharmony_ci    0,                                          /* tp_str */
52977db96d56Sopenharmony_ci    PyObject_GenericGetAttr,                    /* tp_getattro */
52987db96d56Sopenharmony_ci    0,                                          /* tp_setattro */
52997db96d56Sopenharmony_ci    0,                                          /* tp_as_buffer */
53007db96d56Sopenharmony_ci    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
53017db96d56Sopenharmony_ci    0,                                          /* tp_doc */
53027db96d56Sopenharmony_ci    (traverseproc)dictview_traverse,            /* tp_traverse */
53037db96d56Sopenharmony_ci    0,                                          /* tp_clear */
53047db96d56Sopenharmony_ci    0,                                          /* tp_richcompare */
53057db96d56Sopenharmony_ci    0,                                          /* tp_weaklistoffset */
53067db96d56Sopenharmony_ci    (getiterfunc)dictvalues_iter,               /* tp_iter */
53077db96d56Sopenharmony_ci    0,                                          /* tp_iternext */
53087db96d56Sopenharmony_ci    dictvalues_methods,                         /* tp_methods */
53097db96d56Sopenharmony_ci    .tp_getset = dictview_getset,
53107db96d56Sopenharmony_ci};
53117db96d56Sopenharmony_ci
53127db96d56Sopenharmony_cistatic PyObject *
53137db96d56Sopenharmony_cidictvalues_new(PyObject *dict, PyObject *Py_UNUSED(ignored))
53147db96d56Sopenharmony_ci{
53157db96d56Sopenharmony_ci    return _PyDictView_New(dict, &PyDictValues_Type);
53167db96d56Sopenharmony_ci}
53177db96d56Sopenharmony_ci
53187db96d56Sopenharmony_cistatic PyObject *
53197db96d56Sopenharmony_cidictvalues_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
53207db96d56Sopenharmony_ci{
53217db96d56Sopenharmony_ci    if (dv->dv_dict == NULL) {
53227db96d56Sopenharmony_ci        Py_RETURN_NONE;
53237db96d56Sopenharmony_ci    }
53247db96d56Sopenharmony_ci    return dictiter_new(dv->dv_dict, &PyDictRevIterValue_Type);
53257db96d56Sopenharmony_ci}
53267db96d56Sopenharmony_ci
53277db96d56Sopenharmony_ci
53287db96d56Sopenharmony_ci/* Returns NULL if cannot allocate a new PyDictKeysObject,
53297db96d56Sopenharmony_ci   but does not set an error */
53307db96d56Sopenharmony_ciPyDictKeysObject *
53317db96d56Sopenharmony_ci_PyDict_NewKeysForClass(void)
53327db96d56Sopenharmony_ci{
53337db96d56Sopenharmony_ci    PyDictKeysObject *keys = new_keys_object(NEXT_LOG2_SHARED_KEYS_MAX_SIZE, 1);
53347db96d56Sopenharmony_ci    if (keys == NULL) {
53357db96d56Sopenharmony_ci        PyErr_Clear();
53367db96d56Sopenharmony_ci    }
53377db96d56Sopenharmony_ci    else {
53387db96d56Sopenharmony_ci        assert(keys->dk_nentries == 0);
53397db96d56Sopenharmony_ci        /* Set to max size+1 as it will shrink by one before each new object */
53407db96d56Sopenharmony_ci        keys->dk_usable = SHARED_KEYS_MAX_SIZE;
53417db96d56Sopenharmony_ci        keys->dk_kind = DICT_KEYS_SPLIT;
53427db96d56Sopenharmony_ci    }
53437db96d56Sopenharmony_ci    return keys;
53447db96d56Sopenharmony_ci}
53457db96d56Sopenharmony_ci
53467db96d56Sopenharmony_ci#define CACHED_KEYS(tp) (((PyHeapTypeObject*)tp)->ht_cached_keys)
53477db96d56Sopenharmony_ci
53487db96d56Sopenharmony_cistatic int
53497db96d56Sopenharmony_ciinit_inline_values(PyObject *obj, PyTypeObject *tp)
53507db96d56Sopenharmony_ci{
53517db96d56Sopenharmony_ci    assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE);
53527db96d56Sopenharmony_ci    // assert(type->tp_dictoffset > 0);  -- TO DO Update this assert.
53537db96d56Sopenharmony_ci    assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
53547db96d56Sopenharmony_ci    PyDictKeysObject *keys = CACHED_KEYS(tp);
53557db96d56Sopenharmony_ci    assert(keys != NULL);
53567db96d56Sopenharmony_ci    if (keys->dk_usable > 1) {
53577db96d56Sopenharmony_ci        keys->dk_usable--;
53587db96d56Sopenharmony_ci    }
53597db96d56Sopenharmony_ci    Py_ssize_t size = shared_keys_usable_size(keys);
53607db96d56Sopenharmony_ci    assert(size > 0);
53617db96d56Sopenharmony_ci    PyDictValues *values = new_values(size);
53627db96d56Sopenharmony_ci    if (values == NULL) {
53637db96d56Sopenharmony_ci        PyErr_NoMemory();
53647db96d56Sopenharmony_ci        return -1;
53657db96d56Sopenharmony_ci    }
53667db96d56Sopenharmony_ci    assert(((uint8_t *)values)[-1] >= size+2);
53677db96d56Sopenharmony_ci    ((uint8_t *)values)[-2] = 0;
53687db96d56Sopenharmony_ci    for (int i = 0; i < size; i++) {
53697db96d56Sopenharmony_ci        values->values[i] = NULL;
53707db96d56Sopenharmony_ci    }
53717db96d56Sopenharmony_ci    *_PyObject_ValuesPointer(obj) = values;
53727db96d56Sopenharmony_ci    return 0;
53737db96d56Sopenharmony_ci}
53747db96d56Sopenharmony_ci
53757db96d56Sopenharmony_ciint
53767db96d56Sopenharmony_ci_PyObject_InitializeDict(PyObject *obj)
53777db96d56Sopenharmony_ci{
53787db96d56Sopenharmony_ci    PyTypeObject *tp = Py_TYPE(obj);
53797db96d56Sopenharmony_ci    if (tp->tp_dictoffset == 0) {
53807db96d56Sopenharmony_ci        return 0;
53817db96d56Sopenharmony_ci    }
53827db96d56Sopenharmony_ci    if (tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) {
53837db96d56Sopenharmony_ci        OBJECT_STAT_INC(new_values);
53847db96d56Sopenharmony_ci        return init_inline_values(obj, tp);
53857db96d56Sopenharmony_ci    }
53867db96d56Sopenharmony_ci    PyObject *dict;
53877db96d56Sopenharmony_ci    if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE) && CACHED_KEYS(tp)) {
53887db96d56Sopenharmony_ci        dictkeys_incref(CACHED_KEYS(tp));
53897db96d56Sopenharmony_ci        dict = new_dict_with_shared_keys(CACHED_KEYS(tp));
53907db96d56Sopenharmony_ci    }
53917db96d56Sopenharmony_ci    else {
53927db96d56Sopenharmony_ci        dict = PyDict_New();
53937db96d56Sopenharmony_ci    }
53947db96d56Sopenharmony_ci    if (dict == NULL) {
53957db96d56Sopenharmony_ci        return -1;
53967db96d56Sopenharmony_ci    }
53977db96d56Sopenharmony_ci    PyObject **dictptr = _PyObject_DictPointer(obj);
53987db96d56Sopenharmony_ci    *dictptr = dict;
53997db96d56Sopenharmony_ci    return 0;
54007db96d56Sopenharmony_ci}
54017db96d56Sopenharmony_ci
54027db96d56Sopenharmony_cistatic PyObject *
54037db96d56Sopenharmony_cimake_dict_from_instance_attributes(PyDictKeysObject *keys, PyDictValues *values)
54047db96d56Sopenharmony_ci{
54057db96d56Sopenharmony_ci    dictkeys_incref(keys);
54067db96d56Sopenharmony_ci    Py_ssize_t used = 0;
54077db96d56Sopenharmony_ci    Py_ssize_t track = 0;
54087db96d56Sopenharmony_ci    for (Py_ssize_t i = 0; i < shared_keys_usable_size(keys); i++) {
54097db96d56Sopenharmony_ci        PyObject *val = values->values[i];
54107db96d56Sopenharmony_ci        if (val != NULL) {
54117db96d56Sopenharmony_ci            used += 1;
54127db96d56Sopenharmony_ci            track += _PyObject_GC_MAY_BE_TRACKED(val);
54137db96d56Sopenharmony_ci        }
54147db96d56Sopenharmony_ci    }
54157db96d56Sopenharmony_ci    PyObject *res = new_dict(keys, values, used, 0);
54167db96d56Sopenharmony_ci    if (track && res) {
54177db96d56Sopenharmony_ci        _PyObject_GC_TRACK(res);
54187db96d56Sopenharmony_ci    }
54197db96d56Sopenharmony_ci    return res;
54207db96d56Sopenharmony_ci}
54217db96d56Sopenharmony_ci
54227db96d56Sopenharmony_ciPyObject *
54237db96d56Sopenharmony_ci_PyObject_MakeDictFromInstanceAttributes(PyObject *obj, PyDictValues *values)
54247db96d56Sopenharmony_ci{
54257db96d56Sopenharmony_ci    assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
54267db96d56Sopenharmony_ci    PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
54277db96d56Sopenharmony_ci    OBJECT_STAT_INC(dict_materialized_on_request);
54287db96d56Sopenharmony_ci    return make_dict_from_instance_attributes(keys, values);
54297db96d56Sopenharmony_ci}
54307db96d56Sopenharmony_ci
54317db96d56Sopenharmony_ciint
54327db96d56Sopenharmony_ci_PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
54337db96d56Sopenharmony_ci                              PyObject *name, PyObject *value)
54347db96d56Sopenharmony_ci{
54357db96d56Sopenharmony_ci    PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
54367db96d56Sopenharmony_ci    assert(keys != NULL);
54377db96d56Sopenharmony_ci    assert(values != NULL);
54387db96d56Sopenharmony_ci    assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
54397db96d56Sopenharmony_ci    Py_ssize_t ix = DKIX_EMPTY;
54407db96d56Sopenharmony_ci    if (PyUnicode_CheckExact(name)) {
54417db96d56Sopenharmony_ci        ix = insert_into_dictkeys(keys, name);
54427db96d56Sopenharmony_ci    }
54437db96d56Sopenharmony_ci    if (ix == DKIX_EMPTY) {
54447db96d56Sopenharmony_ci#ifdef Py_STATS
54457db96d56Sopenharmony_ci        if (PyUnicode_CheckExact(name)) {
54467db96d56Sopenharmony_ci            if (shared_keys_usable_size(keys) == SHARED_KEYS_MAX_SIZE) {
54477db96d56Sopenharmony_ci                OBJECT_STAT_INC(dict_materialized_too_big);
54487db96d56Sopenharmony_ci            }
54497db96d56Sopenharmony_ci            else {
54507db96d56Sopenharmony_ci                OBJECT_STAT_INC(dict_materialized_new_key);
54517db96d56Sopenharmony_ci            }
54527db96d56Sopenharmony_ci        }
54537db96d56Sopenharmony_ci        else {
54547db96d56Sopenharmony_ci            OBJECT_STAT_INC(dict_materialized_str_subclass);
54557db96d56Sopenharmony_ci        }
54567db96d56Sopenharmony_ci#endif
54577db96d56Sopenharmony_ci        PyObject *dict = make_dict_from_instance_attributes(keys, values);
54587db96d56Sopenharmony_ci        if (dict == NULL) {
54597db96d56Sopenharmony_ci            return -1;
54607db96d56Sopenharmony_ci        }
54617db96d56Sopenharmony_ci        *_PyObject_ValuesPointer(obj) = NULL;
54627db96d56Sopenharmony_ci        *_PyObject_ManagedDictPointer(obj) = dict;
54637db96d56Sopenharmony_ci        if (value == NULL) {
54647db96d56Sopenharmony_ci            return PyDict_DelItem(dict, name);
54657db96d56Sopenharmony_ci        }
54667db96d56Sopenharmony_ci        else {
54677db96d56Sopenharmony_ci            return PyDict_SetItem(dict, name, value);
54687db96d56Sopenharmony_ci        }
54697db96d56Sopenharmony_ci    }
54707db96d56Sopenharmony_ci    PyObject *old_value = values->values[ix];
54717db96d56Sopenharmony_ci    Py_XINCREF(value);
54727db96d56Sopenharmony_ci    values->values[ix] = value;
54737db96d56Sopenharmony_ci    if (old_value == NULL) {
54747db96d56Sopenharmony_ci        if (value == NULL) {
54757db96d56Sopenharmony_ci            PyErr_Format(PyExc_AttributeError,
54767db96d56Sopenharmony_ci                         "'%.100s' object has no attribute '%U'",
54777db96d56Sopenharmony_ci                         Py_TYPE(obj)->tp_name, name);
54787db96d56Sopenharmony_ci            return -1;
54797db96d56Sopenharmony_ci        }
54807db96d56Sopenharmony_ci        _PyDictValues_AddToInsertionOrder(values, ix);
54817db96d56Sopenharmony_ci    }
54827db96d56Sopenharmony_ci    else {
54837db96d56Sopenharmony_ci        if (value == NULL) {
54847db96d56Sopenharmony_ci            delete_index_from_values(values, ix);
54857db96d56Sopenharmony_ci        }
54867db96d56Sopenharmony_ci        Py_DECREF(old_value);
54877db96d56Sopenharmony_ci    }
54887db96d56Sopenharmony_ci    return 0;
54897db96d56Sopenharmony_ci}
54907db96d56Sopenharmony_ci
54917db96d56Sopenharmony_ciPyObject *
54927db96d56Sopenharmony_ci_PyObject_GetInstanceAttribute(PyObject *obj, PyDictValues *values,
54937db96d56Sopenharmony_ci                              PyObject *name)
54947db96d56Sopenharmony_ci{
54957db96d56Sopenharmony_ci    assert(PyUnicode_CheckExact(name));
54967db96d56Sopenharmony_ci    PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
54977db96d56Sopenharmony_ci    assert(keys != NULL);
54987db96d56Sopenharmony_ci    Py_ssize_t ix = _PyDictKeys_StringLookup(keys, name);
54997db96d56Sopenharmony_ci    if (ix == DKIX_EMPTY) {
55007db96d56Sopenharmony_ci        return NULL;
55017db96d56Sopenharmony_ci    }
55027db96d56Sopenharmony_ci    PyObject *value = values->values[ix];
55037db96d56Sopenharmony_ci    Py_XINCREF(value);
55047db96d56Sopenharmony_ci    return value;
55057db96d56Sopenharmony_ci}
55067db96d56Sopenharmony_ci
55077db96d56Sopenharmony_ciint
55087db96d56Sopenharmony_ci_PyObject_IsInstanceDictEmpty(PyObject *obj)
55097db96d56Sopenharmony_ci{
55107db96d56Sopenharmony_ci    PyTypeObject *tp = Py_TYPE(obj);
55117db96d56Sopenharmony_ci    if (tp->tp_dictoffset == 0) {
55127db96d56Sopenharmony_ci        return 1;
55137db96d56Sopenharmony_ci    }
55147db96d56Sopenharmony_ci    PyObject **dictptr;
55157db96d56Sopenharmony_ci    if (tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) {
55167db96d56Sopenharmony_ci        PyDictValues *values = *_PyObject_ValuesPointer(obj);
55177db96d56Sopenharmony_ci        if (values) {
55187db96d56Sopenharmony_ci            PyDictKeysObject *keys = CACHED_KEYS(tp);
55197db96d56Sopenharmony_ci            for (Py_ssize_t i = 0; i < keys->dk_nentries; i++) {
55207db96d56Sopenharmony_ci                if (values->values[i] != NULL) {
55217db96d56Sopenharmony_ci                    return 0;
55227db96d56Sopenharmony_ci                }
55237db96d56Sopenharmony_ci            }
55247db96d56Sopenharmony_ci            return 1;
55257db96d56Sopenharmony_ci        }
55267db96d56Sopenharmony_ci        dictptr = _PyObject_ManagedDictPointer(obj);
55277db96d56Sopenharmony_ci    }
55287db96d56Sopenharmony_ci    else {
55297db96d56Sopenharmony_ci       dictptr = _PyObject_DictPointer(obj);
55307db96d56Sopenharmony_ci    }
55317db96d56Sopenharmony_ci    PyObject *dict = *dictptr;
55327db96d56Sopenharmony_ci    if (dict == NULL) {
55337db96d56Sopenharmony_ci        return 1;
55347db96d56Sopenharmony_ci    }
55357db96d56Sopenharmony_ci    return ((PyDictObject *)dict)->ma_used == 0;
55367db96d56Sopenharmony_ci}
55377db96d56Sopenharmony_ci
55387db96d56Sopenharmony_ci
55397db96d56Sopenharmony_ciint
55407db96d56Sopenharmony_ci_PyObject_VisitInstanceAttributes(PyObject *self, visitproc visit, void *arg)
55417db96d56Sopenharmony_ci{
55427db96d56Sopenharmony_ci    PyTypeObject *tp = Py_TYPE(self);
55437db96d56Sopenharmony_ci    assert(Py_TYPE(self)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
55447db96d56Sopenharmony_ci    PyDictValues **values_ptr = _PyObject_ValuesPointer(self);
55457db96d56Sopenharmony_ci    if (*values_ptr == NULL) {
55467db96d56Sopenharmony_ci        return 0;
55477db96d56Sopenharmony_ci    }
55487db96d56Sopenharmony_ci    PyDictKeysObject *keys = CACHED_KEYS(tp);
55497db96d56Sopenharmony_ci    for (Py_ssize_t i = 0; i < keys->dk_nentries; i++) {
55507db96d56Sopenharmony_ci        Py_VISIT((*values_ptr)->values[i]);
55517db96d56Sopenharmony_ci    }
55527db96d56Sopenharmony_ci    return 0;
55537db96d56Sopenharmony_ci}
55547db96d56Sopenharmony_ci
55557db96d56Sopenharmony_civoid
55567db96d56Sopenharmony_ci_PyObject_ClearInstanceAttributes(PyObject *self)
55577db96d56Sopenharmony_ci{
55587db96d56Sopenharmony_ci    PyTypeObject *tp = Py_TYPE(self);
55597db96d56Sopenharmony_ci    assert(Py_TYPE(self)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
55607db96d56Sopenharmony_ci    PyDictValues **values_ptr = _PyObject_ValuesPointer(self);
55617db96d56Sopenharmony_ci    if (*values_ptr == NULL) {
55627db96d56Sopenharmony_ci        return;
55637db96d56Sopenharmony_ci    }
55647db96d56Sopenharmony_ci    PyDictKeysObject *keys = CACHED_KEYS(tp);
55657db96d56Sopenharmony_ci    for (Py_ssize_t i = 0; i < keys->dk_nentries; i++) {
55667db96d56Sopenharmony_ci        Py_CLEAR((*values_ptr)->values[i]);
55677db96d56Sopenharmony_ci    }
55687db96d56Sopenharmony_ci}
55697db96d56Sopenharmony_ci
55707db96d56Sopenharmony_civoid
55717db96d56Sopenharmony_ci_PyObject_FreeInstanceAttributes(PyObject *self)
55727db96d56Sopenharmony_ci{
55737db96d56Sopenharmony_ci    PyTypeObject *tp = Py_TYPE(self);
55747db96d56Sopenharmony_ci    assert(Py_TYPE(self)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
55757db96d56Sopenharmony_ci    PyDictValues **values_ptr = _PyObject_ValuesPointer(self);
55767db96d56Sopenharmony_ci    PyDictValues *values = *values_ptr;
55777db96d56Sopenharmony_ci    if (values == NULL) {
55787db96d56Sopenharmony_ci        return;
55797db96d56Sopenharmony_ci    }
55807db96d56Sopenharmony_ci    *values_ptr = NULL;
55817db96d56Sopenharmony_ci    PyDictKeysObject *keys = CACHED_KEYS(tp);
55827db96d56Sopenharmony_ci    for (Py_ssize_t i = 0; i < keys->dk_nentries; i++) {
55837db96d56Sopenharmony_ci        Py_XDECREF(values->values[i]);
55847db96d56Sopenharmony_ci    }
55857db96d56Sopenharmony_ci    free_values(values);
55867db96d56Sopenharmony_ci}
55877db96d56Sopenharmony_ci
55887db96d56Sopenharmony_ciPyObject *
55897db96d56Sopenharmony_ciPyObject_GenericGetDict(PyObject *obj, void *context)
55907db96d56Sopenharmony_ci{
55917db96d56Sopenharmony_ci    PyObject *dict;
55927db96d56Sopenharmony_ci    PyTypeObject *tp = Py_TYPE(obj);
55937db96d56Sopenharmony_ci    if (_PyType_HasFeature(tp, Py_TPFLAGS_MANAGED_DICT)) {
55947db96d56Sopenharmony_ci        PyDictValues **values_ptr = _PyObject_ValuesPointer(obj);
55957db96d56Sopenharmony_ci        PyObject **dictptr = _PyObject_ManagedDictPointer(obj);
55967db96d56Sopenharmony_ci        if (*values_ptr) {
55977db96d56Sopenharmony_ci            assert(*dictptr == NULL);
55987db96d56Sopenharmony_ci            OBJECT_STAT_INC(dict_materialized_on_request);
55997db96d56Sopenharmony_ci            *dictptr = dict = make_dict_from_instance_attributes(CACHED_KEYS(tp), *values_ptr);
56007db96d56Sopenharmony_ci            if (dict != NULL) {
56017db96d56Sopenharmony_ci                *values_ptr = NULL;
56027db96d56Sopenharmony_ci            }
56037db96d56Sopenharmony_ci        }
56047db96d56Sopenharmony_ci        else if (*dictptr == NULL) {
56057db96d56Sopenharmony_ci            *dictptr = dict = PyDict_New();
56067db96d56Sopenharmony_ci        }
56077db96d56Sopenharmony_ci        else {
56087db96d56Sopenharmony_ci            dict = *dictptr;
56097db96d56Sopenharmony_ci        }
56107db96d56Sopenharmony_ci    }
56117db96d56Sopenharmony_ci    else {
56127db96d56Sopenharmony_ci        PyObject **dictptr = _PyObject_DictPointer(obj);
56137db96d56Sopenharmony_ci        if (dictptr == NULL) {
56147db96d56Sopenharmony_ci            PyErr_SetString(PyExc_AttributeError,
56157db96d56Sopenharmony_ci                            "This object has no __dict__");
56167db96d56Sopenharmony_ci            return NULL;
56177db96d56Sopenharmony_ci        }
56187db96d56Sopenharmony_ci        dict = *dictptr;
56197db96d56Sopenharmony_ci        if (dict == NULL) {
56207db96d56Sopenharmony_ci            PyTypeObject *tp = Py_TYPE(obj);
56217db96d56Sopenharmony_ci            if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE) && CACHED_KEYS(tp)) {
56227db96d56Sopenharmony_ci                dictkeys_incref(CACHED_KEYS(tp));
56237db96d56Sopenharmony_ci                *dictptr = dict = new_dict_with_shared_keys(CACHED_KEYS(tp));
56247db96d56Sopenharmony_ci            }
56257db96d56Sopenharmony_ci            else {
56267db96d56Sopenharmony_ci                *dictptr = dict = PyDict_New();
56277db96d56Sopenharmony_ci            }
56287db96d56Sopenharmony_ci        }
56297db96d56Sopenharmony_ci    }
56307db96d56Sopenharmony_ci    Py_XINCREF(dict);
56317db96d56Sopenharmony_ci    return dict;
56327db96d56Sopenharmony_ci}
56337db96d56Sopenharmony_ci
56347db96d56Sopenharmony_ciint
56357db96d56Sopenharmony_ci_PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
56367db96d56Sopenharmony_ci                      PyObject *key, PyObject *value)
56377db96d56Sopenharmony_ci{
56387db96d56Sopenharmony_ci    PyObject *dict;
56397db96d56Sopenharmony_ci    int res;
56407db96d56Sopenharmony_ci    PyDictKeysObject *cached;
56417db96d56Sopenharmony_ci
56427db96d56Sopenharmony_ci    assert(dictptr != NULL);
56437db96d56Sopenharmony_ci    if ((tp->tp_flags & Py_TPFLAGS_HEAPTYPE) && (cached = CACHED_KEYS(tp))) {
56447db96d56Sopenharmony_ci        assert(dictptr != NULL);
56457db96d56Sopenharmony_ci        dict = *dictptr;
56467db96d56Sopenharmony_ci        if (dict == NULL) {
56477db96d56Sopenharmony_ci            dictkeys_incref(cached);
56487db96d56Sopenharmony_ci            dict = new_dict_with_shared_keys(cached);
56497db96d56Sopenharmony_ci            if (dict == NULL)
56507db96d56Sopenharmony_ci                return -1;
56517db96d56Sopenharmony_ci            *dictptr = dict;
56527db96d56Sopenharmony_ci        }
56537db96d56Sopenharmony_ci        if (value == NULL) {
56547db96d56Sopenharmony_ci            res = PyDict_DelItem(dict, key);
56557db96d56Sopenharmony_ci        }
56567db96d56Sopenharmony_ci        else {
56577db96d56Sopenharmony_ci            res = PyDict_SetItem(dict, key, value);
56587db96d56Sopenharmony_ci        }
56597db96d56Sopenharmony_ci    } else {
56607db96d56Sopenharmony_ci        dict = *dictptr;
56617db96d56Sopenharmony_ci        if (dict == NULL) {
56627db96d56Sopenharmony_ci            dict = PyDict_New();
56637db96d56Sopenharmony_ci            if (dict == NULL)
56647db96d56Sopenharmony_ci                return -1;
56657db96d56Sopenharmony_ci            *dictptr = dict;
56667db96d56Sopenharmony_ci        }
56677db96d56Sopenharmony_ci        if (value == NULL) {
56687db96d56Sopenharmony_ci            res = PyDict_DelItem(dict, key);
56697db96d56Sopenharmony_ci        } else {
56707db96d56Sopenharmony_ci            res = PyDict_SetItem(dict, key, value);
56717db96d56Sopenharmony_ci        }
56727db96d56Sopenharmony_ci    }
56737db96d56Sopenharmony_ci    ASSERT_CONSISTENT(dict);
56747db96d56Sopenharmony_ci    return res;
56757db96d56Sopenharmony_ci}
56767db96d56Sopenharmony_ci
56777db96d56Sopenharmony_civoid
56787db96d56Sopenharmony_ci_PyDictKeys_DecRef(PyDictKeysObject *keys)
56797db96d56Sopenharmony_ci{
56807db96d56Sopenharmony_ci    dictkeys_decref(keys);
56817db96d56Sopenharmony_ci}
56827db96d56Sopenharmony_ci
56837db96d56Sopenharmony_cistatic uint32_t next_dict_keys_version = 2;
56847db96d56Sopenharmony_ci
56857db96d56Sopenharmony_ciuint32_t _PyDictKeys_GetVersionForCurrentState(PyDictKeysObject *dictkeys)
56867db96d56Sopenharmony_ci{
56877db96d56Sopenharmony_ci    if (dictkeys->dk_version != 0) {
56887db96d56Sopenharmony_ci        return dictkeys->dk_version;
56897db96d56Sopenharmony_ci    }
56907db96d56Sopenharmony_ci    if (next_dict_keys_version == 0) {
56917db96d56Sopenharmony_ci        return 0;
56927db96d56Sopenharmony_ci    }
56937db96d56Sopenharmony_ci    uint32_t v = next_dict_keys_version++;
56947db96d56Sopenharmony_ci    dictkeys->dk_version = v;
56957db96d56Sopenharmony_ci    return v;
56967db96d56Sopenharmony_ci}
5697