summaryrefslogtreecommitdiff
path: root/libgo/runtime/go-map-range.c
blob: 5dbb92ccb89aade9ed3ac11c6a13836b89ec3de2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/* go-map-range.c -- implement a range clause over a map.

   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 "runtime.h"
#include "go-assert.h"
#include "map.h"

/* Initialize a range over a map.  */

void
__go_mapiterinit (const struct __go_map *h, struct __go_hash_iter *it)
{
  it->entry = NULL;
  if (h != NULL)
    {
      it->map = h;
      it->next_entry = NULL;
      it->bucket = 0;
      --it->bucket;
      __go_mapiternext(it);
    }
}

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

void
__go_mapiternext (struct __go_hash_iter *it)
{
  const void *entry;

  entry = it->next_entry;
  if (entry == NULL)
    {
      const struct __go_map *map;
      uintptr_t bucket;

      map = it->map;
      bucket = it->bucket;
      while (1)
	{
	  ++bucket;
	  if (bucket >= map->__bucket_count)
	    {
	      /* Map iteration is complete.  */
	      it->entry = NULL;
	      return;
	    }
	  entry = map->__buckets[bucket];
	  if (entry != NULL)
	    break;
	}
      it->bucket = bucket;
    }
  it->entry = entry;
  it->next_entry = *(const void * const *) entry;
}

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

void
__go_mapiter1 (struct __go_hash_iter *it, unsigned char *key)
{
  const struct __go_map *map;
  const struct __go_map_descriptor *descriptor;
  const struct __go_type_descriptor *key_descriptor;
  const char *p;

  map = it->map;
  descriptor = map->__descriptor;
  key_descriptor = descriptor->__map_descriptor->__key_type;
  p = it->entry;
  __go_assert (p != NULL);
  __builtin_memcpy (key, p + descriptor->__key_offset, key_descriptor->__size);
}

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

void
__go_mapiter2 (struct __go_hash_iter *it, unsigned char *key,
	       unsigned char *val)
{
  const struct __go_map *map;
  const struct __go_map_descriptor *descriptor;
  const struct __go_map_type *map_descriptor;
  const struct __go_type_descriptor *key_descriptor;
  const struct __go_type_descriptor *val_descriptor;
  const char *p;

  map = it->map;
  descriptor = map->__descriptor;
  map_descriptor = descriptor->__map_descriptor;
  key_descriptor = map_descriptor->__key_type;
  val_descriptor = map_descriptor->__val_type;
  p = it->entry;
  __go_assert (p != NULL);
  __builtin_memcpy (key, p + descriptor->__key_offset,
		    key_descriptor->__size);
  __builtin_memcpy (val, p + descriptor->__val_offset,
		    val_descriptor->__size);
}