@@ -28,10 +28,24 @@ int get_doubling_prime_greater_or_equal_to(int x) {
2828/* map */
2929
3030void mp_map_init (mp_map_t * map , int n ) {
31- map -> alloc = get_doubling_prime_greater_or_equal_to (n + 1 );
31+ if (n == 0 ) {
32+ map -> alloc = 0 ;
33+ map -> table = NULL ;
34+ } else {
35+ map -> alloc = get_doubling_prime_greater_or_equal_to (n + 1 );
36+ map -> table = m_new0 (mp_map_elem_t , map -> alloc );
37+ }
3238 map -> used = 0 ;
3339 map -> all_keys_are_qstrs = 1 ;
34- map -> table = m_new0 (mp_map_elem_t , map -> alloc );
40+ map -> table_is_fixed_array = 0 ;
41+ }
42+
43+ void mp_map_init_fixed_table (mp_map_t * map , int n , const mp_obj_t * table ) {
44+ map -> alloc = n ;
45+ map -> used = n ;
46+ map -> all_keys_are_qstrs = 1 ;
47+ map -> table_is_fixed_array = 1 ;
48+ map -> table = (mp_map_elem_t * )table ;
3549}
3650
3751mp_map_t * mp_map_new (int n ) {
@@ -42,7 +56,9 @@ mp_map_t *mp_map_new(int n) {
4256
4357// Differentiate from mp_map_clear() - semantics is different
4458void mp_map_deinit (mp_map_t * map ) {
45- m_del (mp_map_elem_t , map -> table , map -> alloc );
59+ if (!map -> table_is_fixed_array ) {
60+ m_del (mp_map_elem_t , map -> table , map -> alloc );
61+ }
4662 map -> used = map -> alloc = 0 ;
4763}
4864
@@ -52,15 +68,14 @@ void mp_map_free(mp_map_t *map) {
5268}
5369
5470void mp_map_clear (mp_map_t * map ) {
71+ if (!map -> table_is_fixed_array ) {
72+ m_del (mp_map_elem_t , map -> table , map -> alloc );
73+ }
74+ map -> alloc = 0 ;
5575 map -> used = 0 ;
5676 map -> all_keys_are_qstrs = 1 ;
57- machine_uint_t a = map -> alloc ;
58- map -> alloc = 0 ;
59- map -> table = m_renew (mp_map_elem_t , map -> table , a , map -> alloc );
60- mp_map_elem_t nul = {NULL , NULL };
61- for (uint i = 0 ; i < map -> alloc ; i ++ ) {
62- map -> table [i ] = nul ;
63- }
77+ map -> table_is_fixed_array = 0 ;
78+ map -> table = NULL ;
6479}
6580
6681static void mp_map_rehash (mp_map_t * map ) {
@@ -79,21 +94,37 @@ static void mp_map_rehash(mp_map_t *map) {
7994}
8095
8196mp_map_elem_t * mp_map_lookup (mp_map_t * map , mp_obj_t index , mp_map_lookup_kind_t lookup_kind ) {
97+ // if the map is a fixed array then we must do a brute force linear search
98+ if (map -> table_is_fixed_array ) {
99+ if (lookup_kind != MP_MAP_LOOKUP ) {
100+ return NULL ;
101+ }
102+ for (mp_map_elem_t * elem = & map -> table [0 ], * top = & map -> table [map -> used ]; elem < top ; elem ++ ) {
103+ if (elem -> key == index || (!map -> all_keys_are_qstrs && mp_obj_equal (elem -> key , index ))) {
104+ return elem ;
105+ }
106+ }
107+ return NULL ;
108+ }
109+
110+ // map is a hash table (not a fixed array), so do a hash lookup
111+
82112 machine_uint_t hash ;
83113 hash = mp_obj_hash (index );
84114 if (map -> alloc == 0 ) {
85- if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND ) {
115+ if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND ) {
86116 mp_map_rehash (map );
87117 } else {
88118 return NULL ;
89119 }
90120 }
121+
91122 uint pos = hash % map -> alloc ;
92123 for (;;) {
93124 mp_map_elem_t * elem = & map -> table [pos ];
94125 if (elem -> key == NULL ) {
95126 // not in table
96- if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND ) {
127+ if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND ) {
97128 if (map -> used + 1 >= map -> alloc ) {
98129 // not enough room in table, rehash it
99130 mp_map_rehash (map );
@@ -117,7 +148,7 @@ mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
117148 elem->key = index;
118149 }
119150 */
120- if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND ) {
151+ if (lookup_kind & MP_MAP_LOOKUP_REMOVE_IF_FOUND ) {
121152 map -> used -- ;
122153 // this leaks this memory (but see dict_get_helper)
123154 mp_map_elem_t * retval = m_new (mp_map_elem_t , 1 );
@@ -195,7 +226,7 @@ mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t looku
195226 } else {
196227 return MP_OBJ_NULL ;
197228 }
198- } else if (lookup_kind & MP_MAP_LOOKUP_FIRST || mp_obj_equal (elem , index )) {
229+ } else if (( lookup_kind & MP_MAP_LOOKUP_FIRST ) || mp_obj_equal (elem , index )) {
199230 // found it
200231 if (lookup_kind & MP_MAP_LOOKUP_REMOVE_IF_FOUND ) {
201232 set -> used -- ;
@@ -210,11 +241,8 @@ mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t looku
210241}
211242
212243void mp_set_clear (mp_set_t * set ) {
213- set -> used = 0 ;
214- machine_uint_t a = set -> alloc ;
244+ m_del (mp_obj_t , set -> table , set -> alloc );
215245 set -> alloc = 0 ;
216- set -> table = m_renew (mp_obj_t , set -> table , a , set -> alloc );
217- for (uint i = 0 ; i < set -> alloc ; i ++ ) {
218- set -> table [i ] = NULL ;
219- }
246+ set -> used = 0 ;
247+ set -> table = NULL ;
220248}
0 commit comments