// Copyright 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.

package runtime
#include "runtime.h"
#include "map.h"

typedef struct __go_map Hmap;
typedef struct __go_hash_iter hiter;

/* Access a value in a map, returning a value and a presence indicator.  */

func mapaccess2(t *MapType, h *Hmap, key *byte, val *byte) (present bool) {
	byte *mapval;
	size_t valsize;

	mapval = __go_map_index(h, key, 0);
	valsize = t->__val_type->__size;
	if (mapval == nil) {
		__builtin_memset(val, 0, valsize);
		present = 0;
	} else {
		__builtin_memcpy(val, mapval, valsize);
		present = 1;
	}
}

/* Optionally assign a value to a map (m[k] = v, p).  */

func mapassign2(h *Hmap, key *byte, val *byte, p bool) {
	if (!p) {
		__go_map_delete(h, key);
	} else {
		byte *mapval;
		size_t valsize;

		mapval = __go_map_index(h, key, 1);
		valsize = h->__descriptor->__map_descriptor->__val_type->__size;
		__builtin_memcpy(mapval, val, valsize);
	}
}

/* Delete a key from a map.  */

func mapdelete(h *Hmap, key *byte) {
	__go_map_delete(h, key);
}

/* Initialize a range over a map.  */

func mapiterinit(h *Hmap, it *hiter) {
	__go_mapiterinit(h, it);
}

/* Move to the next iteration, updating *HITER.  */

func mapiternext(it *hiter) {
	__go_mapiternext(it);
}

/* Get the key of the current iteration.  */

func mapiter1(it *hiter, key *byte) {
	__go_mapiter1(it, key);
}

/* Get the key and value of the current iteration.  */

func mapiter2(it *hiter, key *byte, val *byte) {
	__go_mapiter2(it, key, val);
}
