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