diff options
author | Sverker Eriksson <[email protected]> | 2014-01-14 18:13:45 +0100 |
---|---|---|
committer | Björn-Egil Dahlberg <[email protected]> | 2014-01-29 11:08:46 +0100 |
commit | 00f9be42e43913bce9b110382e55bfbdaa9406d0 (patch) | |
tree | 33d6d0ea665e1318c867dac24fc6f71bc4faa0e4 | |
parent | ada36d9024b4ceda974f32a78b5fe39b64f59319 (diff) | |
download | otp-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.c | 18 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE.erl | 5 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 57 |
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); } |