micropython/py/objdict.c

168 wiersze
4.5 KiB
C
Czysty Zwykły widok Historia

#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
#include "map.h"
typedef struct _mp_obj_dict_t {
mp_obj_base_t base;
mp_map_t map;
} mp_obj_dict_t;
2014-01-06 17:17:02 +00:00
static mp_obj_t mp_obj_new_dict_iterator(mp_obj_dict_t *dict, int cur);
static mp_map_elem_t *dict_it_iternext_elem(mp_obj_t self_in);
static void dict_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
mp_obj_dict_t *self = self_in;
bool first = true;
print(env, "{");
2014-01-06 17:17:02 +00:00
mp_obj_t *dict_iter = mp_obj_new_dict_iterator(self, 0);
mp_map_elem_t *next = NULL;
while ((next = dict_it_iternext_elem(dict_iter)) != NULL) {
if (!first) {
print(env, ", ");
}
2014-01-06 17:17:02 +00:00
first = false;
mp_obj_print_helper(print, env, next->key);
print(env, ": ");
mp_obj_print_helper(print, env, next->value);
}
print(env, "}");
}
// args are reverse in the array
static mp_obj_t dict_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
// TODO create from an iterable!
return rt_build_map(0);
}
static mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_dict_t *o = lhs_in;
switch (op) {
case RT_BINARY_OP_SUBSCR:
{
// dict load
mp_map_elem_t *elem = mp_map_lookup_helper(&o->map, rhs_in, false);
if (elem == NULL) {
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_KeyError, "<value>"));
} else {
return elem->value;
}
}
default:
// op not supported
return NULL;
}
}
2014-01-06 17:17:02 +00:00
/******************************************************************************/
/* dict iterator */
typedef struct _mp_obj_dict_it_t {
mp_obj_base_t base;
mp_obj_dict_t *dict;
machine_uint_t cur;
} mp_obj_dict_it_t;
static mp_map_elem_t *dict_it_iternext_elem(mp_obj_t self_in) {
mp_obj_dict_it_t *self = self_in;
machine_uint_t max = self->dict->map.alloc;
mp_map_elem_t *table = self->dict->map.table;
for (int i = self->cur; i < max; i++) {
if (table[i].key != NULL) {
self->cur = i + 1;
return &(table[i]);
}
}
return NULL;
}
mp_obj_t dict_it_iternext(mp_obj_t self_in) {
mp_map_elem_t *next = dict_it_iternext_elem(self_in);
if (next != NULL) {
return next->key;
} else {
return mp_const_stop_iteration;
}
}
static const mp_obj_type_t dict_it_type = {
{ &mp_const_type },
"dict_iterator",
.iternext = dict_it_iternext,
.methods = { { NULL, NULL }, },
};
static mp_obj_t mp_obj_new_dict_iterator(mp_obj_dict_t *dict, int cur) {
mp_obj_dict_it_t *o = m_new_obj(mp_obj_dict_it_t);
o->base.type = &dict_it_type;
o->dict = dict;
o->cur = cur;
return o;
}
static mp_obj_t dict_getiter(mp_obj_t o_in) {
return mp_obj_new_dict_iterator(o_in, 0);
}
/******************************************************************************/
/* dict methods */
static mp_obj_t dict_clear(mp_obj_t self_in) {
assert(MP_OBJ_IS_TYPE(self_in, &dict_type));
mp_obj_dict_t *self = self_in;
mp_map_clear(&self->map);
return mp_const_none;
}
2014-01-06 17:54:04 +00:00
static MP_DEFINE_CONST_FUN_OBJ_1(dict_clear_obj, dict_clear);
2014-01-06 17:17:02 +00:00
/******************************************************************************/
/* dict constructors & etc */
const mp_obj_type_t dict_type = {
{ &mp_const_type },
"dict",
.print = dict_print,
.make_new = dict_make_new,
.binary_op = dict_binary_op,
2014-01-06 17:17:02 +00:00
.getiter = dict_getiter,
.methods = {
{ "clear", &dict_clear_obj },
{ NULL, NULL }, // end-of-list sentinel
},
};
mp_obj_t mp_obj_new_dict(int n_args) {
mp_obj_dict_t *o = m_new_obj(mp_obj_dict_t);
o->base.type = &dict_type;
mp_map_init(&o->map, MP_MAP_OBJ, n_args);
return o;
}
uint mp_obj_dict_len(mp_obj_t self_in) {
mp_obj_dict_t *self = self_in;
2014-01-06 17:54:04 +00:00
return self->map.used;
}
mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) {
assert(MP_OBJ_IS_TYPE(self_in, &dict_type));
mp_obj_dict_t *self = self_in;
mp_map_lookup_helper(&self->map, key, true)->value = value;
return self_in;
}