aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/erl_nif.c
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 /erts/emulator/beam/erl_nif.c
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)
Diffstat (limited to 'erts/emulator/beam/erl_nif.c')
-rw-r--r--erts/emulator/beam/erl_nif.c209
1 files changed, 209 insertions, 0 deletions
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 **
***************************************************************************/