Skip to content

Commit ab04f58

Browse files
committed
Merge pull request adafruit#128 from chipaca/dict_views
dict views now, refactoring later.
2 parents 2d45429 + 9ec3a87 commit ab04f58

2 files changed

Lines changed: 139 additions & 0 deletions

File tree

py/objdict.c

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,17 +246,150 @@ static mp_obj_t dict_update(mp_obj_t self_in, mp_obj_t iterable) {
246246
static MP_DEFINE_CONST_FUN_OBJ_2(dict_update_obj, dict_update);
247247

248248

249+
/******************************************************************************/
250+
/* dict views */
251+
252+
static const mp_obj_type_t dict_view_type;
253+
static const mp_obj_type_t dict_view_it_type;
254+
255+
typedef enum _mp_dict_view_kind_t {
256+
MP_DICT_VIEW_ITEMS,
257+
MP_DICT_VIEW_KEYS,
258+
MP_DICT_VIEW_VALUES,
259+
} mp_dict_view_kind_t;
260+
261+
static char *mp_dict_view_names[] = {"dict_items", "dict_keys", "dict_values"};
262+
263+
typedef struct _mp_obj_dict_view_it_t {
264+
mp_obj_base_t base;
265+
mp_dict_view_kind_t kind;
266+
mp_obj_dict_it_t *iter;
267+
machine_uint_t cur;
268+
} mp_obj_dict_view_it_t;
269+
270+
typedef struct _mp_obj_dict_view_t {
271+
mp_obj_base_t base;
272+
mp_obj_dict_t *dict;
273+
mp_dict_view_kind_t kind;
274+
} mp_obj_dict_view_t;
275+
276+
static mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
277+
assert(MP_OBJ_IS_TYPE(self_in, &dict_view_it_type));
278+
mp_obj_dict_view_it_t *self = self_in;
279+
mp_map_elem_t *next = dict_it_iternext_elem(self->iter);
280+
281+
if (next != NULL) {
282+
switch (self->kind) {
283+
case MP_DICT_VIEW_ITEMS:
284+
{
285+
mp_obj_t items[] = {next->key, next->value};
286+
return mp_obj_new_tuple(2, items);
287+
}
288+
case MP_DICT_VIEW_KEYS:
289+
{
290+
return next->key;
291+
}
292+
case MP_DICT_VIEW_VALUES:
293+
{
294+
return next->value;
295+
}
296+
default:
297+
{
298+
assert(0); /* can't happen */
299+
}
300+
}
301+
} else {
302+
return mp_const_stop_iteration;
303+
}
304+
}
305+
306+
static const mp_obj_type_t dict_view_it_type = {
307+
{ &mp_const_type },
308+
"dict_view_iterator",
309+
.iternext = dict_view_it_iternext,
310+
.methods = NULL, /* set operations still to come */
311+
};
312+
313+
static mp_obj_t dict_view_getiter(mp_obj_t view_in) {
314+
assert(MP_OBJ_IS_TYPE(view_in, &dict_view_type));
315+
mp_obj_dict_view_t *view = view_in;
316+
mp_obj_dict_view_it_t *o = m_new_obj(mp_obj_dict_view_it_t);
317+
o->base.type = &dict_view_it_type;
318+
o->kind = view->kind;
319+
o->iter = mp_obj_new_dict_iterator(view->dict, 0);
320+
return o;
321+
}
322+
323+
324+
static void dict_view_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
325+
assert(MP_OBJ_IS_TYPE(self_in, &dict_view_type));
326+
mp_obj_dict_view_t *self = self_in;
327+
bool first = true;
328+
print(env, mp_dict_view_names[self->kind]);
329+
print(env, "([");
330+
mp_obj_t *self_iter = dict_view_getiter(self);
331+
mp_obj_t *next = NULL;
332+
while ((next = dict_view_it_iternext(self_iter)) != mp_const_stop_iteration) {
333+
if (!first) {
334+
print(env, ", ");
335+
}
336+
first = false;
337+
mp_obj_print_helper(print, env, next);
338+
}
339+
print(env, "])");
340+
}
341+
342+
static const mp_obj_type_t dict_view_type = {
343+
{ &mp_const_type },
344+
"dict_view",
345+
.print = dict_view_print,
346+
.getiter = dict_view_getiter,
347+
};
348+
349+
mp_obj_t mp_obj_new_dict_view(mp_obj_dict_t *dict, mp_dict_view_kind_t kind) {
350+
mp_obj_dict_view_t *o = m_new_obj(mp_obj_dict_view_t);
351+
o->base.type = &dict_view_type;
352+
o->dict = dict;
353+
o->kind = kind;
354+
return o;
355+
}
356+
357+
358+
static mp_obj_t dict_view(mp_obj_t self_in, mp_dict_view_kind_t kind) {
359+
assert(MP_OBJ_IS_TYPE(self_in, &dict_type));
360+
mp_obj_dict_t *self = self_in;
361+
return mp_obj_new_dict_view(self, kind);
362+
}
363+
364+
static mp_obj_t dict_items(mp_obj_t self_in) {
365+
return dict_view(self_in, MP_DICT_VIEW_ITEMS);
366+
}
367+
static MP_DEFINE_CONST_FUN_OBJ_1(dict_items_obj, dict_items);
368+
369+
static mp_obj_t dict_keys(mp_obj_t self_in) {
370+
return dict_view(self_in, MP_DICT_VIEW_KEYS);
371+
}
372+
static MP_DEFINE_CONST_FUN_OBJ_1(dict_keys_obj, dict_keys);
373+
374+
static mp_obj_t dict_values(mp_obj_t self_in) {
375+
return dict_view(self_in, MP_DICT_VIEW_VALUES);
376+
}
377+
static MP_DEFINE_CONST_FUN_OBJ_1(dict_values_obj, dict_values);
378+
249379
/******************************************************************************/
250380
/* dict constructors & etc */
251381

252382
static const mp_method_t dict_type_methods[] = {
253383
{ "clear", &dict_clear_obj },
254384
{ "copy", &dict_copy_obj },
255385
{ "get", &dict_get_obj },
386+
{ "items", &dict_items_obj },
387+
{ "keys", &dict_keys_obj },
256388
{ "pop", &dict_pop_obj },
257389
{ "popitem", &dict_popitem_obj },
258390
{ "setdefault", &dict_setdefault_obj },
259391
{ "update", &dict_update_obj },
392+
{ "values", &dict_values_obj },
260393
{ NULL, NULL }, // end-of-list sentinel
261394
};
262395

tests/basics/tests/dict_views.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
d = {1: 2}
2+
for m in d.items, d.values, d.keys:
3+
print(m())
4+
print(list(m()))
5+
6+
# set operations still to come

0 commit comments

Comments
 (0)