diff options
author | Björn-Egil Dahlberg <[email protected]> | 2014-01-13 16:23:56 +0100 |
---|---|---|
committer | Björn-Egil Dahlberg <[email protected]> | 2014-01-29 11:08:44 +0100 |
commit | 39c35199f5118a59f337b695a934c6bfcbf0813b (patch) | |
tree | 1d2fe0359bebfced54621425906097dc87dc9fdf /erts/emulator | |
parent | 4db2458bba34884448d3b3752dce74c17d92c698 (diff) | |
download | otp-39c35199f5118a59f337b695a934c6bfcbf0813b.tar.gz otp-39c35199f5118a59f337b695a934c6bfcbf0813b.tar.bz2 otp-39c35199f5118a59f337b695a934c6bfcbf0813b.zip |
erts: Let erlang:binary_to_term/1 handle unsorted Maps
Maps may be encoded with keys in arbitrary order. This is fine,
as long as keys are unique.
Diffstat (limited to 'erts/emulator')
-rw-r--r-- | erts/emulator/beam/external.c | 35 |
1 files changed, 26 insertions, 9 deletions
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c index e8b77b9f37..57251286c8 100644 --- a/erts/emulator/beam/external.c +++ b/erts/emulator/beam/external.c @@ -3790,24 +3790,41 @@ dec_term_atom_common: } } - /* Iterate through all the maps and check for validity + /* Iterate through all the maps and check for validity and sort keys * - done here for when we know it is complete. */ while (maps_head) { - Eterm *keys; - Sint arity; + map_t *mp = (map_t*)maps_head; + Eterm *ks = map_get_keys(mp); + Eterm *vs = map_get_values(mp); + Uint sz = map_get_size(mp); + Uint ix,jx; + Eterm tmp; + int c; next = (Eterm *)(EXPAND_POINTER(*maps_head)); - keys = tuple_val(*(maps_head + 2)); - arity = arityval(*keys++); - while(arity-- > 1) { - if (CMP_TERM(keys[arity-1],keys[arity]) >= 0) { - goto error; + /* sort */ + + for ( ix = 1; ix < sz; ix++) { + jx = ix; + while( jx > 0 && (c = CMP_TERM(ks[jx],ks[jx-1])) <= 0 ) { + /* identical key -> error */ + if (c == 0) goto error; + + tmp = ks[jx]; + ks[jx] = ks[jx - 1]; + ks[jx - 1] = tmp; + + tmp = vs[jx]; + vs[jx] = vs[jx - 1]; + vs[jx - 1] = tmp; + + jx--; } - } + } *maps_head = MAP_HEADER; maps_head = next; } |