STATIC mp_obj_t dict_update(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { assert(MP_OBJ_IS_DICT_TYPE(args[0])); mp_obj_dict_t *self = MP_OBJ_CAST(args[0]); mp_arg_check_num(n_args, kwargs->used, 1, 2, true); if (n_args == 2) { // given a positional argument if (MP_OBJ_IS_DICT_TYPE(args[1])) { // update from other dictionary (make sure other is not self) if (args[1] != args[0]) { mp_uint_t cur = 0; mp_map_elem_t *elem = NULL; while ((elem = dict_iter_next((mp_obj_dict_t*)args[1], &cur)) != NULL) { mp_map_lookup(&self->map, elem->key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = elem->value; } } } else { // update from a generic iterable of pairs mp_obj_t iter = mp_getiter(args[1]); mp_obj_t next = NULL; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { mp_obj_t inneriter = mp_getiter(next); mp_obj_t key = mp_iternext(inneriter); mp_obj_t value = mp_iternext(inneriter); mp_obj_t stop = mp_iternext(inneriter); if (key == MP_OBJ_STOP_ITERATION || value == MP_OBJ_STOP_ITERATION || stop != MP_OBJ_STOP_ITERATION) { nlr_raise(mp_obj_new_exception_msg( &mp_type_ValueError, "dictionary update sequence has the wrong length")); } else { mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; } } } } // update the dict with any keyword args for (mp_uint_t i = 0; i < kwargs->alloc; i++) { if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) { mp_map_lookup(&self->map, kwargs->table[i].key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = kwargs->table[i].value; } } return mp_const_none; }
STATIC mp_obj_t dict_get_helper(size_t n_args, const mp_obj_t *args, mp_map_lookup_kind_t lookup_kind) { mp_check_self(MP_OBJ_IS_DICT_TYPE(args[0])); mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]); mp_map_elem_t *elem = mp_map_lookup(&self->map, args[1], lookup_kind); mp_obj_t value; if (elem == NULL || elem->value == MP_OBJ_NULL) { if (n_args == 2) { if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, args[1])); } else { value = mp_const_none; } } else { value = args[2]; } if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) { elem->value = value; } } else { value = elem->value; if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) { elem->value = MP_OBJ_NULL; // so that GC can collect the deleted value } } return value; }
STATIC mp_obj_t dict_clear(mp_obj_t self_in) { mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_map_clear(&self->map); return mp_const_none; }
STATIC mp_obj_t dict_clear(mp_obj_t self_in) { assert(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_CAST(self_in); mp_map_clear(&self->map); return mp_const_none; }
STATIC mp_obj_t dict_setdefault(size_t n_args, const mp_obj_t *args) { mp_check_self(MP_OBJ_IS_DICT_TYPE(args[0])); mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]); return dict_get_helper(&self->map, args[1], n_args == 3 ? args[2] : MP_OBJ_NULL, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); }
STATIC mp_obj_t dict_setdefault(mp_uint_t n_args, const mp_obj_t *args) { assert(2 <= n_args && n_args <= 3); assert(MP_OBJ_IS_DICT_TYPE(args[0])); return dict_get_helper(&((mp_obj_dict_t *)args[0])->map, args[1], n_args == 3 ? args[2] : MP_OBJ_NULL, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); }
STATIC mp_obj_t dict_pop(mp_uint_t n_args, const mp_obj_t *args) { assert(2 <= n_args && n_args <= 3); assert(MP_OBJ_IS_DICT_TYPE(args[0])); mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]); return dict_get_helper(&self->map, args[1], n_args == 3 ? args[2] : MP_OBJ_NULL, MP_MAP_LOOKUP_REMOVE_IF_FOUND); }
STATIC mp_obj_t dict_copy(mp_obj_t self_in) { mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t other_out = mp_obj_new_dict(self->map.alloc); mp_obj_dict_t *other = MP_OBJ_TO_PTR(other_out); other->base.type = self->base.type; other->map.used = self->map.used; other->map.all_keys_are_qstrs = self->map.all_keys_are_qstrs; other->map.is_fixed = 0; other->map.is_ordered = self->map.is_ordered; memcpy(other->map.table, self->map.table, self->map.alloc * sizeof(mp_map_elem_t)); return other_out; }
STATIC mp_obj_t dict_popitem(mp_obj_t self_in) { mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); size_t cur = 0; mp_map_elem_t *next = dict_iter_next(self, &cur); if (next == NULL) { mp_raise_msg(&mp_type_KeyError, "popitem(): dictionary is empty"); } self->map.used--; mp_obj_t items[] = {next->key, next->value}; next->key = MP_OBJ_SENTINEL; // must mark key as sentinel to indicate that it was deleted next->value = MP_OBJ_NULL; mp_obj_t tuple = mp_obj_new_tuple(2, items); return tuple; }
mp_map_t *mp_obj_dict_get_map(mp_obj_t self_in) { mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); return &self->map; }
mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) { mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; return self_in; }
STATIC mp_obj_t dict_view(mp_obj_t self_in, mp_dict_view_kind_t kind) { mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); return mp_obj_new_dict_view(self_in, kind); }
mp_obj_t mp_obj_dict_delete(mp_obj_t self_in, mp_obj_t key) { mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); dict_get_helper(&self->map, key, MP_OBJ_NULL, MP_MAP_LOOKUP_REMOVE_IF_FOUND); return self_in; }
mp_map_t *mp_obj_dict_get_map(mp_obj_t self_in) { assert(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_CAST(self_in); return &self->map; }