/* go-reflect-map.c -- map reflection support for Go. Copyright 2009, 2010 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. */ #include #include #include "runtime.h" #include "go-alloc.h" #include "go-assert.h" #include "go-type.h" #include "map.h" /* This file implements support for reflection on maps. These functions are called from reflect/value.go. */ extern void *mapaccess (struct __go_map_type *, void *, void *) __asm__ (GOSYM_PREFIX "reflect.mapaccess"); void * mapaccess (struct __go_map_type *mt, void *m, void *key) { struct __go_map *map = (struct __go_map *) m; __go_assert ((mt->__common.__code & GO_CODE_MASK) == GO_MAP); if (map == NULL) return NULL; else return __go_map_index (map, key, 0); } extern void mapassign (struct __go_map_type *, void *, void *, void *) __asm__ (GOSYM_PREFIX "reflect.mapassign"); void mapassign (struct __go_map_type *mt, void *m, void *key, void *val) { struct __go_map *map = (struct __go_map *) m; void *p; __go_assert ((mt->__common.__code & GO_CODE_MASK) == GO_MAP); if (map == NULL) runtime_panicstring ("assignment to entry in nil map"); p = __go_map_index (map, key, 1); __builtin_memcpy (p, val, mt->__val_type->__size); } extern void mapdelete (struct __go_map_type *, void *, void *) __asm__ (GOSYM_PREFIX "reflect.mapdelete"); void mapdelete (struct __go_map_type *mt, void *m, void *key) { struct __go_map *map = (struct __go_map *) m; __go_assert ((mt->__common.__code & GO_CODE_MASK) == GO_MAP); if (map == NULL) return; __go_map_delete (map, key); } extern int32_t maplen (void *) __asm__ (GOSYM_PREFIX "reflect.maplen"); int32_t maplen (void *m) { struct __go_map *map = (struct __go_map *) m; if (map == NULL) return 0; return (int32_t) map->__element_count; } extern unsigned char *mapiterinit (struct __go_map_type *, void *) __asm__ (GOSYM_PREFIX "reflect.mapiterinit"); unsigned char * mapiterinit (struct __go_map_type *mt, void *m) { struct __go_hash_iter *it; __go_assert ((mt->__common.__code & GO_CODE_MASK) == GO_MAP); it = __go_alloc (sizeof (struct __go_hash_iter)); __go_mapiterinit ((struct __go_map *) m, it); return (unsigned char *) it; } extern void mapiternext (void *) __asm__ (GOSYM_PREFIX "reflect.mapiternext"); void mapiternext (void *it) { __go_mapiternext ((struct __go_hash_iter *) it); } extern void *mapiterkey (void *) __asm__ (GOSYM_PREFIX "reflect.mapiterkey"); void * mapiterkey (void *ita) { struct __go_hash_iter *it = (struct __go_hash_iter *) ita; const struct __go_type_descriptor *key_descriptor; void *key; if (it->entry == NULL) return NULL; key_descriptor = it->map->__descriptor->__map_descriptor->__key_type; key = __go_alloc (key_descriptor->__size); __go_mapiter1 (it, key); return key; } /* Make a new map. We have to build our own map descriptor. */ extern struct __go_map *makemap (const struct __go_map_type *) __asm__ (GOSYM_PREFIX "reflect.makemap"); struct __go_map * makemap (const struct __go_map_type *t) { struct __go_map_descriptor *md; unsigned int o; const struct __go_type_descriptor *kt; const struct __go_type_descriptor *vt; md = (struct __go_map_descriptor *) __go_alloc (sizeof (*md)); md->__map_descriptor = t; o = sizeof (void *); kt = t->__key_type; o = (o + kt->__field_align - 1) & ~ (kt->__field_align - 1); md->__key_offset = o; o += kt->__size; vt = t->__val_type; o = (o + vt->__field_align - 1) & ~ (vt->__field_align - 1); md->__val_offset = o; o += vt->__size; o = (o + sizeof (void *) - 1) & ~ (sizeof (void *) - 1); o = (o + kt->__field_align - 1) & ~ (kt->__field_align - 1); o = (o + vt->__field_align - 1) & ~ (vt->__field_align - 1); md->__entry_size = o; return __go_new_map (md, 0); } extern _Bool ismapkey (const struct __go_type_descriptor *) __asm__ (GOSYM_PREFIX "reflect.ismapkey"); _Bool ismapkey (const struct __go_type_descriptor *typ) { return (typ != NULL && (void *) typ->__hashfn->fn != (void *) __go_type_hash_error); }