@@ -87,15 +87,19 @@ void mp_map_init(mp_map_t *map, size_t n) {
87
87
map -> used = 0 ;
88
88
map -> all_keys_are_qstrs = 1 ;
89
89
map -> is_fixed = 0 ;
90
+ #if !MICROPY_PY_MAP_ORDERED
90
91
map -> is_ordered = 0 ;
92
+ #endif
91
93
}
92
94
93
95
void mp_map_init_fixed_table (mp_map_t * map , size_t n , const mp_obj_t * table ) {
94
96
map -> alloc = n ;
95
97
map -> used = n ;
96
98
map -> all_keys_are_qstrs = 1 ;
97
99
map -> is_fixed = 1 ;
100
+ #if !MICROPY_PY_MAP_ORDERED
98
101
map -> is_ordered = 1 ;
102
+ #endif
99
103
map -> table = (mp_map_elem_t * )table ;
100
104
}
101
105
@@ -118,6 +122,7 @@ void mp_map_clear(mp_map_t *map) {
118
122
map -> table = NULL ;
119
123
}
120
124
125
+ #if !MICROPY_PY_MAP_ORDERED
121
126
STATIC void mp_map_rehash (mp_map_t * map ) {
122
127
size_t old_alloc = map -> alloc ;
123
128
size_t new_alloc = get_hash_alloc_greater_or_equal_to (map -> alloc + 1 );
@@ -136,6 +141,7 @@ STATIC void mp_map_rehash(mp_map_t *map) {
136
141
}
137
142
m_del (mp_map_elem_t , old_table , old_alloc );
138
143
}
144
+ #endif
139
145
140
146
// MP_MAP_LOOKUP behaviour:
141
147
// - returns NULL if not found, else the slot it was found in with key,value non-null
@@ -167,134 +173,139 @@ mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
167
173
}
168
174
169
175
// if the map is an ordered array then we must do a brute force linear search
176
+ #if !MICROPY_PY_MAP_ORDERED
170
177
if (map -> is_ordered ) {
171
- for (mp_map_elem_t * elem = & map -> table [0 ], * top = & map -> table [map -> used ]; elem < top ; elem ++ ) {
172
- if (elem -> key == index || (!compare_only_ptrs && mp_obj_equal (elem -> key , index ))) {
173
- #if MICROPY_PY_COLLECTIONS_ORDEREDDICT
174
- if (MP_UNLIKELY (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND )) {
175
- // remove the found element by moving the rest of the array down
176
- mp_obj_t value = elem -> value ;
177
- -- map -> used ;
178
- memmove (elem , elem + 1 , (top - elem - 1 ) * sizeof (* elem ));
179
- // put the found element after the end so the caller can access it if needed
180
- // note: caller must NULL the value so the GC can clean up (e.g. see dict_get_helper).
181
- elem = & map -> table [map -> used ];
182
- elem -> key = MP_OBJ_NULL ;
183
- elem -> value = value ;
184
- }
185
- #endif
186
- return elem ;
178
+ #endif
179
+ for (mp_map_elem_t * elem = & map -> table [0 ], * top = & map -> table [map -> used ]; elem < top ; elem ++ ) {
180
+ if (elem -> key == index || (!compare_only_ptrs && mp_obj_equal (elem -> key , index ))) {
181
+ #if MICROPY_PY_COLLECTIONS_ORDEREDDICT
182
+ if (MP_UNLIKELY (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND )) {
183
+ // remove the found element by moving the rest of the array down
184
+ mp_obj_t value = elem -> value ;
185
+ -- map -> used ;
186
+ memmove (elem , elem + 1 , (top - elem - 1 ) * sizeof (* elem ));
187
+ // put the found element after the end so the caller can access it if needed
188
+ // note: caller must NULL the value so the GC can clean up (e.g. see dict_get_helper).
189
+ elem = & map -> table [map -> used ];
190
+ elem -> key = MP_OBJ_NULL ;
191
+ elem -> value = value ;
187
192
}
193
+ #endif
194
+ return elem ;
188
195
}
189
- #if MICROPY_PY_COLLECTIONS_ORDEREDDICT
190
- if (MP_LIKELY (lookup_kind != MP_MAP_LOOKUP_ADD_IF_NOT_FOUND )) {
191
- return NULL ;
192
- }
193
- if (map -> used == map -> alloc ) {
194
- // TODO: Alloc policy
195
- map -> alloc += 4 ;
196
- map -> table = m_renew (mp_map_elem_t , map -> table , map -> used , map -> alloc );
197
- mp_seq_clear (map -> table , map -> used , map -> alloc , sizeof (* map -> table ));
198
- }
199
- mp_map_elem_t * elem = map -> table + map -> used ++ ;
200
- elem -> key = index ;
201
- if (!mp_obj_is_qstr (index )) {
202
- map -> all_keys_are_qstrs = 0 ;
203
- }
204
- return elem ;
205
- #else
196
+ }
197
+ #if MICROPY_PY_COLLECTIONS_ORDEREDDICT
198
+ if (MP_LIKELY (lookup_kind != MP_MAP_LOOKUP_ADD_IF_NOT_FOUND )) {
206
199
return NULL ;
207
- #endif
208
200
}
201
+ if (map -> used == map -> alloc ) {
202
+ // TODO: Alloc policy
203
+ map -> alloc += 4 ;
204
+ map -> table = m_renew (mp_map_elem_t , map -> table , map -> used , map -> alloc );
205
+ mp_seq_clear (map -> table , map -> used , map -> alloc , sizeof (* map -> table ));
206
+ }
207
+ mp_map_elem_t * elem = map -> table + map -> used ++ ;
208
+ elem -> key = index ;
209
+ if (!mp_obj_is_qstr (index )) {
210
+ map -> all_keys_are_qstrs = 0 ;
211
+ }
212
+ return elem ;
213
+ #else
214
+ return NULL ;
215
+ #endif
216
+
217
+ #if !MICROPY_PY_MAP_ORDERED
218
+ }
209
219
210
- // map is a hash table (not an ordered array), so do a hash lookup
220
+ // map is a hash table (not an ordered array), so do a hash lookup
211
221
212
- if (map -> alloc == 0 ) {
222
+ if (map -> alloc == 0 ) {
223
+ if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND ) {
224
+ mp_map_rehash (map );
225
+ } else {
226
+ return NULL ;
227
+ }
228
+ }
229
+
230
+ // get hash of index, with fast path for common case of qstr
231
+ mp_uint_t hash ;
232
+ if (mp_obj_is_qstr (index )) {
233
+ hash = qstr_hash (MP_OBJ_QSTR_VALUE (index ));
234
+ } else {
235
+ hash = MP_OBJ_SMALL_INT_VALUE (mp_unary_op (MP_UNARY_OP_HASH , index ));
236
+ }
237
+
238
+ size_t pos = hash % map -> alloc ;
239
+ size_t start_pos = pos ;
240
+ mp_map_elem_t * avail_slot = NULL ;
241
+ for (;;) {
242
+ mp_map_elem_t * slot = & map -> table [pos ];
243
+ if (slot -> key == MP_OBJ_NULL ) {
244
+ // found NULL slot, so index is not in table
213
245
if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND ) {
214
- mp_map_rehash (map );
246
+ map -> used += 1 ;
247
+ if (avail_slot == NULL ) {
248
+ avail_slot = slot ;
249
+ }
250
+ avail_slot -> key = index ;
251
+ avail_slot -> value = MP_OBJ_NULL ;
252
+ if (!mp_obj_is_qstr (index )) {
253
+ map -> all_keys_are_qstrs = 0 ;
254
+ }
255
+ return avail_slot ;
215
256
} else {
216
257
return NULL ;
217
258
}
259
+ } else if (slot -> key == MP_OBJ_SENTINEL ) {
260
+ // found deleted slot, remember for later
261
+ if (avail_slot == NULL ) {
262
+ avail_slot = slot ;
263
+ }
264
+ } else if (slot -> key == index || (!compare_only_ptrs && mp_obj_equal (slot -> key , index ))) {
265
+ // found index
266
+ // Note: CPython does not replace the index; try x={True:'true'};x[1]='one';x
267
+ if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND ) {
268
+ // delete element in this slot
269
+ map -> used -- ;
270
+ if (map -> table [(pos + 1 ) % map -> alloc ].key == MP_OBJ_NULL ) {
271
+ // optimisation if next slot is empty
272
+ slot -> key = MP_OBJ_NULL ;
273
+ } else {
274
+ slot -> key = MP_OBJ_SENTINEL ;
275
+ }
276
+ // keep slot->value so that caller can access it if needed
277
+ }
278
+ return slot ;
218
279
}
219
280
220
- // get hash of index, with fast path for common case of qstr
221
- mp_uint_t hash ;
222
- if (mp_obj_is_qstr (index )) {
223
- hash = qstr_hash (MP_OBJ_QSTR_VALUE (index ));
224
- } else {
225
- hash = MP_OBJ_SMALL_INT_VALUE (mp_unary_op (MP_UNARY_OP_HASH , index ));
226
- }
281
+ // not yet found, keep searching in this table
282
+ pos = (pos + 1 ) % map -> alloc ;
227
283
228
- size_t pos = hash % map -> alloc ;
229
- size_t start_pos = pos ;
230
- mp_map_elem_t * avail_slot = NULL ;
231
- for (;;) {
232
- mp_map_elem_t * slot = & map -> table [pos ];
233
- if (slot -> key == MP_OBJ_NULL ) {
234
- // found NULL slot, so index is not in table
235
- if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND ) {
236
- map -> used += 1 ;
237
- if (avail_slot == NULL ) {
238
- avail_slot = slot ;
239
- }
284
+ if (pos == start_pos ) {
285
+ // search got back to starting position, so index is not in table
286
+ if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND ) {
287
+ if (avail_slot != NULL ) {
288
+ // there was an available slot, so use that
289
+ map -> used ++ ;
240
290
avail_slot -> key = index ;
241
291
avail_slot -> value = MP_OBJ_NULL ;
242
292
if (!mp_obj_is_qstr (index )) {
243
293
map -> all_keys_are_qstrs = 0 ;
244
294
}
245
295
return avail_slot ;
246
296
} else {
247
- return NULL ;
248
- }
249
- } else if (slot -> key == MP_OBJ_SENTINEL ) {
250
- // found deleted slot, remember for later
251
- if (avail_slot == NULL ) {
252
- avail_slot = slot ;
253
- }
254
- } else if (slot -> key == index || (!compare_only_ptrs && mp_obj_equal (slot -> key , index ))) {
255
- // found index
256
- // Note: CPython does not replace the index; try x={True:'true'};x[1]='one';x
257
- if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND ) {
258
- // delete element in this slot
259
- map -> used -- ;
260
- if (map -> table [(pos + 1 ) % map -> alloc ].key == MP_OBJ_NULL ) {
261
- // optimisation if next slot is empty
262
- slot -> key = MP_OBJ_NULL ;
263
- } else {
264
- slot -> key = MP_OBJ_SENTINEL ;
265
- }
266
- // keep slot->value so that caller can access it if needed
267
- }
268
- return slot ;
269
- }
270
-
271
- // not yet found, keep searching in this table
272
- pos = (pos + 1 ) % map -> alloc ;
273
-
274
- if (pos == start_pos ) {
275
- // search got back to starting position, so index is not in table
276
- if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND ) {
277
- if (avail_slot != NULL ) {
278
- // there was an available slot, so use that
279
- map -> used ++ ;
280
- avail_slot -> key = index ;
281
- avail_slot -> value = MP_OBJ_NULL ;
282
- if (!mp_obj_is_qstr (index )) {
283
- map -> all_keys_are_qstrs = 0 ;
284
- }
285
- return avail_slot ;
286
- } else {
287
- // not enough room in table, rehash it
288
- mp_map_rehash (map );
289
- // restart the search for the new element
290
- start_pos = pos = hash % map -> alloc ;
291
- }
292
- } else {
293
- return NULL ;
297
+ // not enough room in table, rehash it
298
+ mp_map_rehash (map );
299
+ // restart the search for the new element
300
+ start_pos = pos = hash % map -> alloc ;
294
301
}
302
+ } else {
303
+ return NULL ;
295
304
}
296
305
}
297
306
}
307
+ #endif // !MICROPY_PY_MAP_ORDERED
308
+ }
298
309
299
310
/******************************************************************************/
300
311
/* set */
0 commit comments