aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn-Egil Dahlberg <[email protected]>2013-11-08 15:34:05 +0100
committerBjörn-Egil Dahlberg <[email protected]>2014-01-29 11:08:40 +0100
commite0eb6d5bafcebc1c24b0a538e50a1d55a3724f01 (patch)
tree5fddadbcc6100f4200e2e5d10fa7a505896736f5
parent1a234c9eba8ac2c78f97e5f3e33521b8cc5d3748 (diff)
downloadotp-e0eb6d5bafcebc1c24b0a538e50a1d55a3724f01.tar.gz
otp-e0eb6d5bafcebc1c24b0a538e50a1d55a3724f01.tar.bz2
otp-e0eb6d5bafcebc1c24b0a538e50a1d55a3724f01.zip
erts: Add NIFs for Maps
- int enif_is_map(ErlNifEnv* env, ERL_NIF_TERM map) - int enif_get_map_size(ErlNifEnv *env, ERL_NIF_TERM, int*) - ERL_NIF_TERM enif_make_new_map(ErlNifEnv *env) - int enif_make_map_put(ErlNifEnv *env, ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM value, ERL_NIF_TERM* map_out) - int enif_get_map_value(ErlNifEnv *env, ERL_NIF_TERM map, ERL_NIF_TERM key, ERL_NIF_TERM* value) - int enif_find_map_value(ErlNifEnv *env, ERL_NIF_TERM map, ERL_NIF_TERM key, ERL_NIF_TERM* value) - int enif_make_map_update(ErlNifEnv *env, ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM value, ERL_NIF_TERM* map_out) - int enif_make_map_remove(ErlNifEnv *env, ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM* map_out) - int enif_map_iterator_create(ErlNifEnv *env, ERL_NIF_TERM map, ErlNifMapIterator *iter) - void enif_map_iterator_destroy(ErlNifEnv *env, ErlNifMapIterator *iter) - int enif_map_iterator_next(ErlNifEnv *env, ErlNifMapIterator *iter) - int enif_map_iterator_get_pair(ErlNifEnv *env, ErlNifMapIterator *iter, ERL_NIF_TERM *key, ERL_NIF_TERM *value)
-rw-r--r--erts/emulator/beam/erl_map.c443
-rw-r--r--erts/emulator/beam/erl_map.h6
-rw-r--r--erts/emulator/beam/erl_nif.c209
-rw-r--r--erts/emulator/beam/erl_nif.h26
-rw-r--r--erts/emulator/beam/erl_nif_api_funcs.h33
5 files changed, 511 insertions, 206 deletions
diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c
index 27734276f9..98aeee634b 100644
--- a/erts/emulator/beam/erl_map.c
+++ b/erts/emulator/beam/erl_map.c
@@ -111,28 +111,39 @@ BIF_RETTYPE maps_to_list_1(BIF_ALIST_1) {
* return value if key *equals* a key in the map
*/
-BIF_RETTYPE maps_find_2(BIF_ALIST_2) {
- if (is_map(BIF_ARG_2)) {
- Eterm *hp, *ks,*vs, key, res;
- map_t *mp;
- Uint n,i;
+int erts_maps_find(Eterm key, Eterm map, Eterm *value) {
- mp = (map_t*)map_val(BIF_ARG_2);
- key = BIF_ARG_1;
- n = map_get_size(mp);
- ks = map_get_keys(mp);
- vs = map_get_values(mp);
+ Eterm *ks,*vs;
+ map_t *mp;
+ Uint n,i;
- for( i = 0; i < n; i++) {
- if (CMP(ks[i], key)==0) {
- hp = HAlloc(BIF_P, 3);
- res = make_tuple(hp);
- *hp++ = make_arityval(2);
- *hp++ = am_ok;
- *hp++ = vs[i];
- BIF_RET(res);
- }
+ mp = (map_t*)map_val(map);
+ n = map_get_size(mp);
+ ks = map_get_keys(mp);
+ vs = map_get_values(mp);
+
+ for( i = 0; i < n; i++) {
+ if (CMP(ks[i], key)==0) {
+ *value = vs[i];
+ return 1;
+ }
+ }
+ return 0;
+}
+
+BIF_RETTYPE maps_find_2(BIF_ALIST_2) {
+ if (is_map(BIF_ARG_2)) {
+ Eterm *hp, value,res;
+
+ if (erts_maps_find(BIF_ARG_1, BIF_ARG_2, &value)) {
+ hp = HAlloc(BIF_P, 3);
+ res = make_tuple(hp);
+ *hp++ = make_arityval(2);
+ *hp++ = am_ok;
+ *hp++ = value;
+ BIF_RET(res);
}
+
BIF_RET(am_error);
}
BIF_ERROR(BIF_P, BADARG);
@@ -142,43 +153,54 @@ BIF_RETTYPE maps_find_2(BIF_ALIST_2) {
* exception bad_key if none matches
*/
-BIF_RETTYPE maps_get_2(BIF_ALIST_2) {
- if (is_map(BIF_ARG_2)) {
- Eterm *hp, *ks,*vs, key, error;
- map_t *mp;
- Uint n,i;
- char *s_error;
- mp = (map_t*)map_val(BIF_ARG_2);
- key = BIF_ARG_1;
- n = map_get_size(mp);
-
- if (n == 0)
- goto error;
+int erts_maps_get(Eterm key, Eterm map, Eterm *value) {
+ Eterm *ks,*vs;
+ map_t *mp;
+ Uint n,i;
- ks = map_get_keys(mp);
- vs = map_get_values(mp);
+ mp = (map_t*)map_val(map);
+ n = map_get_size(mp);
- if (is_immed(key)) {
- for( i = 0; i < n; i++) {
- if (ks[i] == key) {
- BIF_RET(vs[i]);
- }
- }
- }
+ if (n == 0)
+ return 0;
+
+ ks = map_get_keys(mp);
+ vs = map_get_values(mp);
+ if (is_immed(key)) {
for( i = 0; i < n; i++) {
- if (eq(ks[i], key)) {
- BIF_RET(vs[i]);
+ if (ks[i] == key) {
+ *value = vs[i];
+ return 1;
}
}
-error:
+ }
+
+ for( i = 0; i < n; i++) {
+ if (eq(ks[i], key)) {
+ *value = vs[i];
+ return 1;
+ }
+ }
+ return 0;
+}
+
+BIF_RETTYPE maps_get_2(BIF_ALIST_2) {
+ if (is_map(BIF_ARG_2)) {
+ Eterm *hp;
+ Eterm value, error;
+ char *s_error;
+
+ if (erts_maps_get(BIF_ARG_1, BIF_ARG_2, &value)) {
+ BIF_RET(value);
+ }
s_error = "bad_key";
error = am_atom_put(s_error, sys_strlen(s_error));
hp = HAlloc(BIF_P, 3);
- BIF_P->fvalue = TUPLE2(hp, error, key);
+ BIF_P->fvalue = TUPLE2(hp, error, BIF_ARG_1);
BIF_ERROR(BIF_P, EXC_ERROR_2);
}
BIF_ERROR(BIF_P, BADARG);
@@ -460,7 +482,7 @@ BIF_RETTYPE maps_new_0(BIF_ALIST_0) {
Eterm tup;
map_t *mp;
- hp = HAlloc(BIF_P, (3 + 1));
+ hp = HAlloc(BIF_P, (MAP_HEADER_SIZE + 1));
tup = make_tuple(hp);
*hp++ = make_arityval(0);
@@ -475,183 +497,197 @@ BIF_RETTYPE maps_new_0(BIF_ALIST_0) {
/* maps:put/3
*/
-BIF_RETTYPE maps_put_3(BIF_ALIST_3) {
- if (is_map(BIF_ARG_3)) {
- Sint n,i;
- Sint c = 0;
- Eterm* hp, *shp;
- Eterm *ks,*vs, res, key, tup;
- map_t *mp = (map_t*)map_val(BIF_ARG_3);
-
- key = BIF_ARG_1;
- n = map_get_size(mp);
-
- if (n == 0) {
- hp = HAlloc(BIF_P, 4 + 2);
- tup = make_tuple(hp);
- *hp++ = make_arityval(1);
- *hp++ = key;
- res = make_map(hp);
- *hp++ = MAP_HEADER;
- *hp++ = 1;
- *hp++ = tup;
- *hp++ = BIF_ARG_2;
+Eterm erts_maps_put(Process *p, Eterm key, Eterm value, Eterm map) {
+ Sint n,i;
+ Sint c = 0;
+ Eterm* hp, *shp;
+ Eterm *ks,*vs, res, tup;
+ map_t *mp = (map_t*)map_val(map);
- BIF_RET(res);
- }
-
- ks = map_get_keys(mp);
- vs = map_get_values(mp);
- /* only allocate for values,
- * assume key-tuple will be intact
- */
+ n = map_get_size(mp);
- hp = HAlloc(BIF_P, 3 + n);
- shp = hp; /* save hp, used if optimistic update fails */
- res = make_map(hp);
+ if (n == 0) {
+ hp = HAlloc(p, MAP_HEADER_SIZE + 1 + 2);
+ tup = make_tuple(hp);
+ *hp++ = make_arityval(1);
+ *hp++ = key;
+ res = make_map(hp);
*hp++ = MAP_HEADER;
- *hp++ = n;
- *hp++ = mp->keys;
+ *hp++ = 1;
+ *hp++ = tup;
+ *hp++ = value;
- if (is_immed(key)) {
- for( i = 0; i < n; i ++) {
- if (ks[i] == key) {
- *hp++ = BIF_ARG_2;
- vs++;
- c = 1;
- } else {
- *hp++ = *vs++;
- }
+ return res;
+ }
+
+ ks = map_get_keys(mp);
+ vs = map_get_values(mp);
+
+ /* only allocate for values,
+ * assume key-tuple will be intact
+ */
+
+ hp = HAlloc(p, MAP_HEADER_SIZE + n);
+ shp = hp; /* save hp, used if optimistic update fails */
+ res = make_map(hp);
+ *hp++ = MAP_HEADER;
+ *hp++ = n;
+ *hp++ = mp->keys;
+
+ if (is_immed(key)) {
+ for( i = 0; i < n; i ++) {
+ if (ks[i] == key) {
+ *hp++ = value;
+ vs++;
+ c = 1;
+ } else {
+ *hp++ = *vs++;
}
- } else {
- for( i = 0; i < n; i ++) {
- if (eq(ks[i], key)) {
- *hp++ = BIF_ARG_2;
- vs++;
- c = 1;
- } else {
- *hp++ = *vs++;
- }
+ }
+ } else {
+ for( i = 0; i < n; i ++) {
+ if (eq(ks[i], key)) {
+ *hp++ = value;
+ vs++;
+ c = 1;
+ } else {
+ *hp++ = *vs++;
}
}
+ }
- if (c)
- BIF_RET(res);
+ if (c)
+ return res;
- /* need to make a new tuple,
- * use old hp since it needs to be recreated anyway.
- */
- tup = make_tuple(shp);
- *shp++ = make_arityval(n+1);
+ /* need to make a new tuple,
+ * use old hp since it needs to be recreated anyway.
+ */
+ tup = make_tuple(shp);
+ *shp++ = make_arityval(n+1);
- hp = HAlloc(BIF_P, 3 + n + 1);
- res = make_map(hp);
- *hp++ = MAP_HEADER;
- *hp++ = n + 1;
- *hp++ = tup;
+ hp = HAlloc(p, 3 + n + 1);
+ res = make_map(hp);
+ *hp++ = MAP_HEADER;
+ *hp++ = n + 1;
+ *hp++ = tup;
- ks = map_get_keys(mp);
- vs = map_get_values(mp);
+ ks = map_get_keys(mp);
+ vs = map_get_values(mp);
- ASSERT(n >= 0);
+ ASSERT(n >= 0);
- /* copy map in order */
- while (n && ((c = CMP(*ks, key)) < 0)) {
- *shp++ = *ks++;
- *hp++ = *vs++;
- n--;
- }
+ /* copy map in order */
+ while (n && ((c = CMP(*ks, key)) < 0)) {
+ *shp++ = *ks++;
+ *hp++ = *vs++;
+ n--;
+ }
- *shp++ = key;
- *hp++ = BIF_ARG_2;
+ *shp++ = key;
+ *hp++ = value;
- ASSERT(n >= 0);
+ ASSERT(n >= 0);
- while(n--) {
- *shp++ = *ks++;
- *hp++ = *vs++;
- }
- /* we have one word remaining
- * this will work out fine once we get the size word
- * in the header.
- */
- *shp = make_pos_bignum_header(0);
- BIF_RET(res);
+ while(n--) {
+ *shp++ = *ks++;
+ *hp++ = *vs++;
}
+ /* we have one word remaining
+ * this will work out fine once we get the size word
+ * in the header.
+ */
+ *shp = make_pos_bignum_header(0);
+ return res;
+}
+BIF_RETTYPE maps_put_3(BIF_ALIST_3) {
+ if (is_map(BIF_ARG_3)) {
+ BIF_RET(erts_maps_put(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3));
+ }
BIF_ERROR(BIF_P, BADARG);
}
/* maps:remove/3
*/
-BIF_RETTYPE maps_remove_2(BIF_ALIST_2) {
- if (is_map(BIF_ARG_2)) {
- Sint n;
- Sint found = 0;
- Uint need;
- Eterm *thp, *mhp;
- Eterm *ks, *vs, res, key,tup;
- map_t *mp = (map_t*)map_val(BIF_ARG_2);
+int erts_maps_remove(Process *p, Eterm key, Eterm map, Eterm *res) {
+ Sint n;
+ Sint found = 0;
+ Uint need;
+ Eterm *thp, *mhp;
+ Eterm *ks, *vs, tup;
+ map_t *mp = (map_t*)map_val(map);
- key = BIF_ARG_1;
- n = map_get_size(mp);
+ n = map_get_size(mp);
- if (n == 0)
- BIF_RET(BIF_ARG_2);
+ if (n == 0) {
+ *res = map;
+ return 1;
+ }
- ks = map_get_keys(mp);
- vs = map_get_values(mp);
+ ks = map_get_keys(mp);
+ vs = map_get_values(mp);
- /* Assume key exists.
- * Release allocated if it didn't.
- * Allocate key tuple first.
- */
+ /* Assume key exists.
+ * Release allocated if it didn't.
+ * Allocate key tuple first.
+ */
- need = n + 1 - 1 + 3 + n - 1; /* tuple - 1 + map - 1 */
- thp = HAlloc(BIF_P, need);
- mhp = thp + n; /* offset with tuple heap size */
+ need = n + 1 - 1 + 3 + n - 1; /* tuple - 1 + map - 1 */
+ thp = HAlloc(p, need);
+ mhp = thp + n; /* offset with tuple heap size */
- tup = make_tuple(thp);
- *thp++ = make_arityval(n - 1);
+ tup = make_tuple(thp);
+ *thp++ = make_arityval(n - 1);
- res = make_map(mhp);
- *mhp++ = MAP_HEADER;
- *mhp++ = n - 1;
- *mhp++ = tup;
+ *res = make_map(mhp);
+ *mhp++ = MAP_HEADER;
+ *mhp++ = n - 1;
+ *mhp++ = tup;
- if (is_immed(key)) {
- while(n--) {
- if (*ks == key) {
- ks++;
- vs++;
- found = 1;
- } else {
- *mhp++ = *vs++;
- *thp++ = *ks++;
- }
+ if (is_immed(key)) {
+ while(n--) {
+ if (*ks == key) {
+ ks++;
+ vs++;
+ found = 1;
+ } else {
+ *mhp++ = *vs++;
+ *thp++ = *ks++;
}
- } else {
- while(n--) {
- if (eq(*ks, key)) {
- ks++;
- vs++;
- found = 1;
- } else {
- *mhp++ = *vs++;
- *thp++ = *ks++;
- }
+ }
+ } else {
+ while(n--) {
+ if (eq(*ks, key)) {
+ ks++;
+ vs++;
+ found = 1;
+ } else {
+ *mhp++ = *vs++;
+ *thp++ = *ks++;
}
}
+ }
- if (found)
- BIF_RET(res);
+ if (found) {
+ return 1;
+ }
- /* Not found, remove allocated memory
- * and return previous map.
- */
- HRelease(BIF_P, thp + need, thp);
- BIF_RET(BIF_ARG_2);
+ /* Not found, remove allocated memory
+ * and return previous map.
+ */
+ HRelease(p, thp + need, thp);
+
+ *res = map;
+ return 1;
+}
+
+BIF_RETTYPE maps_remove_2(BIF_ALIST_2) {
+ if (is_map(BIF_ARG_2)) {
+ Eterm res;
+ if (erts_maps_remove(BIF_P, BIF_ARG_1, BIF_ARG_2, &res)) {
+ BIF_RET(res);
+ }
}
BIF_ERROR(BIF_P, BADARG);
}
@@ -659,19 +695,15 @@ BIF_RETTYPE maps_remove_2(BIF_ALIST_2) {
/* maps:update/3
*/
-BIF_RETTYPE maps_update_3(BIF_ALIST_3) {
- if (is_map(BIF_ARG_3)) {
+int erts_maps_update(Process *p, Eterm key, Eterm value, Eterm map, Eterm *res) {
Sint n,i;
Sint found = 0;
Eterm* hp,*shp;
- Eterm *ks,*vs, res, key;
- map_t *mp = (map_t*)map_val(BIF_ARG_3);
+ Eterm *ks,*vs;
+ map_t *mp = (map_t*)map_val(map);
- key = BIF_ARG_1;
- n = map_get_size(mp);
-
- if (n == 0) {
- BIF_ERROR(BIF_P, BADARG);
+ if ((n = map_get_size(mp)) == 0) {
+ return 0;
}
ks = map_get_keys(mp);
@@ -681,9 +713,9 @@ BIF_RETTYPE maps_update_3(BIF_ALIST_3) {
* assume key-tuple will be intact
*/
- hp = HAlloc(BIF_P, 3 + n);
+ hp = HAlloc(p, MAP_HEADER_SIZE + n);
shp = hp;
- res = make_map(hp);
+ *res = make_map(hp);
*hp++ = MAP_HEADER;
*hp++ = n;
*hp++ = mp->keys;
@@ -691,7 +723,7 @@ BIF_RETTYPE maps_update_3(BIF_ALIST_3) {
if (is_immed(key)) {
for( i = 0; i < n; i ++) {
if (ks[i] == key) {
- *hp++ = BIF_ARG_2;
+ *hp++ = value;
vs++;
found = 1;
} else {
@@ -701,7 +733,7 @@ BIF_RETTYPE maps_update_3(BIF_ALIST_3) {
} else {
for( i = 0; i < n; i ++) {
if (eq(ks[i], key)) {
- *hp++ = BIF_ARG_2;
+ *hp++ = value;
vs++;
found = 1;
} else {
@@ -710,10 +742,19 @@ BIF_RETTYPE maps_update_3(BIF_ALIST_3) {
}
}
- if (found)
- BIF_RET(res);
+ if (found) {
+ return 1;
+ }
+ HRelease(p, shp + MAP_HEADER_SIZE + n, shp);
+ return 0;
+}
- HRelease(BIF_P, shp + 3 + n, shp);
+BIF_RETTYPE maps_update_3(BIF_ALIST_3) {
+ if (is_map(BIF_ARG_3)) {
+ Eterm res;
+ if (erts_maps_update(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3, &res)) {
+ BIF_RET(res);
+ }
}
BIF_ERROR(BIF_P, BADARG);
}
diff --git a/erts/emulator/beam/erl_map.h b/erts/emulator/beam/erl_map.h
index 4f0d26e100..616ecd24ce 100644
--- a/erts/emulator/beam/erl_map.h
+++ b/erts/emulator/beam/erl_map.h
@@ -62,5 +62,11 @@ typedef struct map_s {
#define MAP_HEADER _make_header(1,_TAG_HEADER_MAP)
#define MAP_HEADER_SIZE (sizeof(map_t) / sizeof(Eterm))
+Eterm erts_maps_put(Process *p, Eterm key, Eterm value, Eterm map);
+int erts_maps_update(Process *p, Eterm key, Eterm value, Eterm map, Eterm *res);
+int erts_maps_find(Eterm key, Eterm map, Eterm *value);
+int erts_maps_get(Eterm key, Eterm map, Eterm *value);
+int erts_maps_remove(Process *p, Eterm key, Eterm map, Eterm *res);
+
#endif
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index e1e213c4eb..c683847aaa 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -31,6 +31,7 @@
#include "bif.h"
#include "error.h"
#include "big.h"
+#include "erl_map.h"
#include "beam_bp.h"
#include "erl_thr_progress.h"
#include "dtrace-wrapper.h"
@@ -1602,6 +1603,214 @@ enif_have_dirty_schedulers()
#endif /* ERL_NIF_DIRTY_SCHEDULER_SUPPORT */
+/* Maps */
+
+int enif_is_map(ErlNifEnv* env, ERL_NIF_TERM term)
+{
+ return is_map(term);
+}
+
+int enif_get_map_size(ErlNifEnv* env, ERL_NIF_TERM term, int *size)
+{
+ if (is_map(term)) {
+ map_t *mp;
+ mp = (map_t*)map_val(term);
+ *size = map_get_size(mp);
+ return 1;
+ }
+ return 0;
+}
+
+ERL_NIF_TERM enif_make_new_map(ErlNifEnv* env)
+{
+ Eterm* hp = alloc_heap(env,MAP_HEADER_SIZE+1);
+ Eterm tup;
+ map_t *mp;
+
+ tup = make_tuple(hp);
+ *hp++ = make_arityval(0);
+ mp = (map_t*)hp;
+ mp->thing_word = MAP_HEADER;
+ mp->size = 0;
+ mp->keys = tup;
+
+ return make_map(mp);
+}
+
+int enif_make_map_put(ErlNifEnv* env,
+ Eterm map_in,
+ Eterm key,
+ Eterm value,
+ Eterm *map_out)
+{
+ if (is_not_map(map_in)) {
+ return 0;
+ }
+ flush_env(env);
+ *map_out = erts_maps_put(env->proc, key, value, map_in);
+ cache_env(env);
+ return 1;
+}
+
+int enif_get_map_value(ErlNifEnv* env,
+ Eterm map,
+ Eterm key,
+ Eterm *value)
+{
+ if (is_not_map(map)) {
+ return 0;
+ }
+ return erts_maps_get(key, map, value);
+}
+
+int enif_find_map_value(ErlNifEnv* env,
+ Eterm map,
+ Eterm key,
+ Eterm *value)
+{
+ if (is_not_map(map)) {
+ return 0;
+ }
+ return erts_maps_get(key, map, value);
+}
+
+int enif_make_map_update(ErlNifEnv* env,
+ Eterm map_in,
+ Eterm key,
+ Eterm value,
+ Eterm *map_out)
+{
+ int res;
+ if (is_not_map(map_in)) {
+ return 0;
+ }
+
+ flush_env(env);
+ res = erts_maps_update(env->proc, key, value, map_in, map_out);
+ cache_env(env);
+ return res;
+}
+
+int enif_make_map_remove(ErlNifEnv* env,
+ Eterm map_in,
+ Eterm key,
+ Eterm *map_out)
+{
+ int res;
+ if (is_not_map(map_in)) {
+ return 0;
+ }
+ flush_env(env);
+ res = erts_maps_remove(env->proc, key, map_in, map_out);
+ cache_env(env);
+ return res;
+}
+
+int enif_map_iterator_create(ErlNifEnv *env,
+ Eterm map,
+ ErlNifMapIterator *iter,
+ ErlNifMapIteratorEntry entry)
+{
+ if (is_map(map)) {
+ map_t *mp = (map_t*)map_val(map);
+ size_t offset;
+
+ switch (entry) {
+ case ERL_NIF_MAP_ITERATOR_HEAD: offset = 0; break;
+ case ERL_NIF_MAP_ITERATOR_TAIL: offset = map_get_size(mp) - 1; break;
+ default: goto error;
+ }
+
+ /* empty maps are ok but will leave the iterator
+ * in bad shape.
+ */
+
+ iter->map = map;
+ iter->ks = ((Eterm *)map_get_keys(mp)) + offset;
+ iter->vs = ((Eterm *)map_get_values(mp)) + offset;
+ iter->t_limit = map_get_size(mp) + 1;
+ iter->h_limit = 0;
+ iter->idx = offset + 1;
+
+ return 1;
+ }
+
+error:
+ iter->map = THE_NON_VALUE;
+ return 0;
+}
+
+void enif_map_iterator_destroy(ErlNifEnv *env, ErlNifMapIterator *iter)
+{
+ /* not used */
+}
+
+int enif_map_iterator_is_tail(ErlNifEnv *env, ErlNifMapIterator *iter)
+{
+ ASSERT(iter->idx >= 0 && (iter->idx <= map_get_size(map_val(iter->map)) + 1));
+ if (is_map(iter->map) && (
+ (iter->t_limit - iter->h_limit) == 1 ||
+ iter->idx == iter->t_limit)) {
+ return 1;
+ }
+ return 0;
+}
+
+int enif_map_iterator_is_head(ErlNifEnv *env, ErlNifMapIterator *iter)
+{
+ ASSERT(iter->idx >= 0 && (iter->idx <= map_get_size(map_val(iter->map)) + 1));
+ if (is_map(iter->map) && (
+ (iter->t_limit - iter->h_limit) == 1 ||
+ iter->idx == iter->h_limit)) {
+ return 1;
+ }
+ return 0;
+}
+
+
+int enif_map_iterator_next(ErlNifEnv *env, ErlNifMapIterator *iter)
+{
+ if (is_map(iter->map) && iter->idx < iter->t_limit) {
+ iter->idx++;
+ if (iter->idx != iter->t_limit) {
+ iter->ks++;
+ iter->vs++;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+int enif_map_iterator_prev(ErlNifEnv *env, ErlNifMapIterator *iter)
+{
+ if (is_map(iter->map) && iter->idx > iter->h_limit ) {
+ iter->idx--;
+ if (iter->idx != iter->h_limit ) {
+ iter->ks--;
+ iter->vs--;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+int enif_map_iterator_get_pair(ErlNifEnv *env,
+ ErlNifMapIterator *iter,
+ Eterm *key,
+ Eterm *value)
+{
+ if (is_map(iter->map) && iter->idx > iter->h_limit && iter->idx < iter->t_limit) {
+ ASSERT(iter->ks >= map_get_keys(map_val(iter->map)) &&
+ iter->ks < (map_get_keys(map_val(iter->map)) + map_get_size(map_val(iter->map))));
+ ASSERT(iter->vs >= map_get_values(map_val(iter->map)) &&
+ iter->vs < (map_get_values(map_val(iter->map)) + map_get_size(map_val(iter->map))));
+ *key = *(iter->ks);
+ *value = *(iter->vs);
+ return 1;
+ }
+ return 0;
+}
+
/***************************************************************************
** load_nif/2 **
***************************************************************************/
diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h
index fb3c359ec9..3c1e13f8a4 100644
--- a/erts/emulator/beam/erl_nif.h
+++ b/erts/emulator/beam/erl_nif.h
@@ -38,14 +38,11 @@
** 2.2: R14B03 enif_is_exception
** 2.3: R15 enif_make_reverse_list, enif_is_number
** 2.4: R16 enif_consume_timeslice
-** 2.5: R17 dirty schedulers
+** 2.5: R17 Maps API additions
+** R17 dirty schedulers
*/
#define ERL_NIF_MAJOR_VERSION 2
-#ifdef ERL_NIF_DIRTY_SCHEDULER_SUPPORT
#define ERL_NIF_MINOR_VERSION 5
-#else
-#define ERL_NIF_MINOR_VERSION 4
-#endif
#include <stdlib.h>
@@ -168,6 +165,7 @@ typedef int ErlNifTSDKey;
typedef ErlDrvThreadOpts ErlNifThreadOpts;
+<<<<<<< HEAD
#ifdef ERL_NIF_DIRTY_SCHEDULER_SUPPORT
typedef enum
{
@@ -175,6 +173,24 @@ typedef enum
ERL_NIF_DIRTY_JOB_IO_BOUND = 2
}ErlNifDirtyTaskFlags;
#endif
+=======
+typedef struct
+{
+ /* use a lot of memory, structure may change */
+ ERL_NIF_TERM map;
+ ErlNifUInt64 h_limit;
+ ErlNifUInt64 t_limit;
+ ErlNifUInt64 idx;
+ ERL_NIF_TERM *ks;
+ ERL_NIF_TERM *vs;
+} ErlNifMapIterator;
+
+typedef enum {
+ ERL_NIF_MAP_ITERATOR_HEAD = 1,
+ ERL_NIF_MAP_ITERATOR_TAIL = 2
+} ErlNifMapIteratorEntry;
+
+>>>>>>> erts: Add NIFs for Maps
#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_))
# define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) RET_TYPE (*NAME) ARGS
diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h
index f5b27dfdfa..2cabfd4ce1 100644
--- a/erts/emulator/beam/erl_nif_api_funcs.h
+++ b/erts/emulator/beam/erl_nif_api_funcs.h
@@ -149,6 +149,23 @@ ERL_NIF_API_FUNC_DECL(int,enif_is_on_dirty_scheduler,(ErlNifEnv*));
ERL_NIF_API_FUNC_DECL(int,enif_have_dirty_schedulers,(void));
#endif
+ERL_NIF_API_FUNC_DECL(int, enif_is_map, (ErlNifEnv* env, ERL_NIF_TERM term));
+ERL_NIF_API_FUNC_DECL(int, enif_get_map_size, (ErlNifEnv* env, ERL_NIF_TERM term, int *size));
+ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM, enif_make_new_map, (ErlNifEnv* env));
+ERL_NIF_API_FUNC_DECL(int, enif_make_map_put, (ErlNifEnv* env, ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM value, ERL_NIF_TERM* map_out));
+ERL_NIF_API_FUNC_DECL(int, enif_get_map_value, (ErlNifEnv* env, ERL_NIF_TERM map, ERL_NIF_TERM key, ERL_NIF_TERM* value));
+ERL_NIF_API_FUNC_DECL(int, enif_find_map_value, (ErlNifEnv* env, ERL_NIF_TERM map, ERL_NIF_TERM key, ERL_NIF_TERM* value));
+ERL_NIF_API_FUNC_DECL(int, enif_make_map_update, (ErlNifEnv* env, ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM value, ERL_NIF_TERM* map_out));
+ERL_NIF_API_FUNC_DECL(int, enif_make_map_remove, (ErlNifEnv* env, ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM* map_out));
+ERL_NIF_API_FUNC_DECL(int, enif_map_iterator_create, (ErlNifEnv *env, ERL_NIF_TERM map, ErlNifMapIterator *iter, ErlNifMapIteratorEntry entry));
+ERL_NIF_API_FUNC_DECL(void, enif_map_iterator_destroy, (ErlNifEnv *env, ErlNifMapIterator *iter));
+ERL_NIF_API_FUNC_DECL(int, enif_map_iterator_is_head, (ErlNifEnv *env, ErlNifMapIterator *iter));
+ERL_NIF_API_FUNC_DECL(int, enif_map_iterator_is_tail, (ErlNifEnv *env, ErlNifMapIterator *iter));
+ERL_NIF_API_FUNC_DECL(int, enif_map_iterator_next, (ErlNifEnv *env, ErlNifMapIterator *iter));
+ERL_NIF_API_FUNC_DECL(int, enif_map_iterator_prev, (ErlNifEnv *env, ErlNifMapIterator *iter));
+ERL_NIF_API_FUNC_DECL(int, enif_map_iterator_get_pair, (ErlNifEnv *env, ErlNifMapIterator *iter, ERL_NIF_TERM *key, ERL_NIF_TERM *value));
+
+
/*
** Add new entries here to keep compatibility on Windows!!!
*/
@@ -281,6 +298,22 @@ ERL_NIF_API_FUNC_DECL(int,enif_have_dirty_schedulers,(void));
# define enif_have_dirty_schedulers ERL_NIF_API_FUNC_MACRO(enif_have_dirty_schedulers)
#endif
+# define enif_is_map ERL_NIF_API_FUNC_MACRO(enif_is_map)
+# define enif_get_map_size ERL_NIF_API_FUNC_MACRO(enif_get_map_size)
+# define enif_make_new_map ERL_NIF_FUNC_MACRO(enif_make_new_map)
+# define enif_make_map_put ERL_NIF_FUNC_MACRO(enif_map_map_put)
+# define enif_get_map_value ERL_NIF_FUNC_MACRO(enif_get_map_value)
+# define enif_find_map_value ERL_NIF_FUNC_MACRO(enif_find_map_value)
+# define enif_make_map_update ERL_NIF_FUNC_MACRO(enif_make_map_update)
+# define enif_make_map_remove ERL_NIF_FUNC_MACRO(enif_make_map_remove)
+# define enif_map_iterator_create ERL_NIF_FUNC_MACRO(enif_map_iterator_create)
+# define enif_map_iterator_destroy ERL_NIF_FUNC_MACRO(enif_map_iterator_destroy)
+# define enif_map_iterator_is_head ERL_NIF_FUNC_MACRO(enif_map_iterator_is_head)
+# define enif_map_iterator_is_tail ERL_NIF_FUNC_MACRO(enif_map_iterator_is_tail)
+# define enif_map_iterator_next ERL_NIF_FUNC_MACRO(enif_map_iterator_next)
+# define enif_map_iterator_prev ERL_NIF_FUNC_MACRO(enif_map_iterator_prev)
+# define enif_map_iterator_get_pair NIF_FUNC_MACRO(enif_map_iterator_get_pair)
+
/*
** Add new entries here
*/