aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2014-01-14 18:13:45 +0100
committerBjörn-Egil Dahlberg <[email protected]>2014-01-29 11:08:46 +0100
commit00f9be42e43913bce9b110382e55bfbdaa9406d0 (patch)
tree33d6d0ea665e1318c867dac24fc6f71bc4faa0e4
parentada36d9024b4ceda974f32a78b5fe39b64f59319 (diff)
downloadotp-00f9be42e43913bce9b110382e55bfbdaa9406d0.tar.gz
otp-00f9be42e43913bce9b110382e55bfbdaa9406d0.tar.bz2
otp-00f9be42e43913bce9b110382e55bfbdaa9406d0.zip
erts: Fix map iterator bug when reverting from end of map position
and simplify code by ignoring h_limit which is always zero.
-rw-r--r--erts/emulator/beam/erl_nif.c18
-rw-r--r--erts/emulator/test/nif_SUITE.erl5
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_SUITE.c57
3 files changed, 53 insertions, 27 deletions
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index c6f7c8adb5..6fceb8a0ba 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -1759,13 +1759,10 @@ int enif_map_iterator_next(ErlNifEnv *env, ErlNifMapIterator *iter)
ASSERT(iter && is_map(iter->map));
if (iter->idx < iter->t_limit) {
iter->idx++;
- if (iter->idx != iter->t_limit) {
- iter->ks++;
- iter->vs++;
- return 1;
- }
+ iter->ks++;
+ iter->vs++;
}
- return 0;
+ return (iter->idx != iter->t_limit);
}
int enif_map_iterator_prev(ErlNifEnv *env, ErlNifMapIterator *iter)
@@ -1773,13 +1770,10 @@ int enif_map_iterator_prev(ErlNifEnv *env, ErlNifMapIterator *iter)
ASSERT(iter && is_map(iter->map));
if (iter->idx > 0) {
iter->idx--;
- if (iter->idx != 0) {
- iter->ks--;
- iter->vs--;
- return 1;
- }
+ iter->ks--;
+ iter->vs--;
}
- return 0;
+ return (iter->idx > 0);
}
int enif_map_iterator_get_pair(ErlNifEnv *env,
diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl
index 5b7c310aa4..a34f70c618 100644
--- a/erts/emulator/test/nif_SUITE.erl
+++ b/erts/emulator/test/nif_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2014. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -449,6 +449,9 @@ maps(Config) when is_list(Config) ->
io:format("Pairs: ~p~nMap: ~p~nReturned: ~p~n", [lists:sort(Pairs),M,R]),
Is = lists:sort(Pairs),
Is = lists:reverse(RIs),
+
+ #{} = maps_from_list([]),
+ {[],[]} = sorted_list_from_maps(#{}),
ok.
api_macros(doc) -> ["Test macros enif_make_list<N> and enif_make_tuple<N>"];
diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
index a0316a7861..8549d277de 100644
--- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
+++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2009-2013. All Rights Reserved.
+ * Copyright Ericsson AB 2009-2014. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -1564,31 +1564,60 @@ static ERL_NIF_TERM sorted_list_from_maps(ErlNifEnv* env, int argc, const ERL_NI
ERL_NIF_TERM map = argv[0];
ERL_NIF_TERM list_f = enif_make_list(env, 0); /* NIL */
ERL_NIF_TERM list_b = enif_make_list(env, 0); /* NIL */
- ERL_NIF_TERM key, value;
- ErlNifMapIterator iter;
+ ERL_NIF_TERM key, value, k2, v2;
+ ErlNifMapIterator iter_f;
+ ErlNifMapIterator iter_b;
+ int cnt, next_ret, prev_ret;
if (argc != 1 && !enif_is_map(env, map))
- return enif_make_badarg(env);
+ return enif_make_int(env, __LINE__);
- if(!enif_map_iterator_create(env, map, &iter, ERL_NIF_MAP_ITERATOR_HEAD))
- return enif_make_badarg(env);
+ if(!enif_map_iterator_create(env, map, &iter_f, ERL_NIF_MAP_ITERATOR_HEAD))
+ return enif_make_int(env, __LINE__);
- while(enif_map_iterator_get_pair(env,&iter,&key,&value)) {
+ cnt = 0;
+ while(enif_map_iterator_get_pair(env,&iter_f,&key,&value)) {
+ if (cnt && !next_ret)
+ return enif_make_int(env, __LINE__);
list_f = enif_make_list_cell(env, enif_make_tuple2(env, key, value), list_f);
- enif_map_iterator_next(env,&iter);
+ next_ret = enif_map_iterator_next(env,&iter_f);
+ cnt++;
}
+ if (cnt && next_ret)
+ return enif_make_int(env, __LINE__);
- enif_map_iterator_destroy(env, &iter);
+ if(!enif_map_iterator_create(env, map, &iter_b, ERL_NIF_MAP_ITERATOR_TAIL))
+ return enif_make_int(env, __LINE__);
- if(!enif_map_iterator_create(env, map, &iter, ERL_NIF_MAP_ITERATOR_TAIL))
- return enif_make_badarg(env);
+ cnt = 0;
+ while(enif_map_iterator_get_pair(env,&iter_b,&key,&value)) {
+ if (cnt && !prev_ret)
+ return enif_make_int(env, __LINE__);
+
+ /* Test that iter_f can step "backwards" */
+ if (!enif_map_iterator_prev(env,&iter_f)
+ || !enif_map_iterator_get_pair(env,&iter_f,&k2,&v2)
+ || k2 != key || v2 != value) {
+ return enif_make_int(env, __LINE__);
+ }
- while(enif_map_iterator_get_pair(env,&iter,&key,&value)) {
list_b = enif_make_list_cell(env, enif_make_tuple2(env, key, value), list_b);
- enif_map_iterator_prev(env,&iter);
+ prev_ret = enif_map_iterator_prev(env,&iter_b);
+ }
+
+ if (cnt) {
+ if (prev_ret || enif_map_iterator_prev(env,&iter_f))
+ return enif_make_int(env, __LINE__);
+
+ /* Test that iter_b can step "backwards" one step */
+ if (!enif_map_iterator_next(env, &iter_b)
+ || !enif_map_iterator_get_pair(env,&iter_b,&k2,&v2)
+ || k2 != key || v2 != value)
+ return enif_make_int(env, __LINE__);
}
- enif_map_iterator_destroy(env, &iter);
+ enif_map_iterator_destroy(env, &iter_f);
+ enif_map_iterator_destroy(env, &iter_b);
return enif_make_tuple2(env, list_f, list_b);
}