aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/doc/src/erl_ext_dist.xml29
-rw-r--r--erts/emulator/Makefile.in20
-rw-r--r--erts/emulator/beam/dist.h6
-rw-r--r--erts/emulator/beam/external.c55
-rw-r--r--erts/emulator/test/map_SUITE.erl19
-rw-r--r--lib/debugger/test/map_SUITE.erl9
-rw-r--r--lib/erl_interface/doc/src/ei.xml34
-rw-r--r--lib/erl_interface/include/ei.h6
-rw-r--r--lib/erl_interface/src/connect/ei_connect.c5
-rw-r--r--lib/erl_interface/src/connect/ei_connect_int.h3
-rw-r--r--lib/erl_interface/src/decode/decode_skip.c10
-rw-r--r--lib/erl_interface/src/decode/decode_tuple_header.c23
-rw-r--r--lib/erl_interface/src/encode/encode_tuple_header.c19
-rw-r--r--lib/erl_interface/src/misc/ei_decode_term.c3
-rw-r--r--lib/erl_interface/src/misc/ei_x_encode.c12
-rw-r--r--lib/erl_interface/test/all_SUITE_data/ei_runner.c6
-rw-r--r--lib/erl_interface/test/all_SUITE_data/ei_runner.h3
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE.erl11
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c490
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractNode.java5
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangMap.java4
-rw-r--r--lib/jinterface/test/jinterface_SUITE_data/Maps.java8
-rw-r--r--lib/kernel/include/dist.hrl3
-rw-r--r--lib/kernel/src/dist_util.erl5
24 files changed, 565 insertions, 223 deletions
diff --git a/erts/doc/src/erl_ext_dist.xml b/erts/doc/src/erl_ext_dist.xml
index f91ed78122..fa083db4c7 100644
--- a/erts/doc/src/erl_ext_dist.xml
+++ b/erts/doc/src/erl_ext_dist.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2007</year>
- <year>2013</year>
+ <year>2014</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -573,6 +573,33 @@
</section>
<section>
+ <marker id="MAP_EXT"/>
+ <title>MAP_EXT</title>
+
+ <table align="left">
+ <row>
+ <cell align="center">1</cell>
+ <cell align="center">4</cell>
+ <cell align="center">N</cell>
+ </row>
+ <row>
+ <cell align="center">116</cell>
+ <cell align="center">Arity</cell>
+ <cell align="center">Pairs</cell>
+ </row>
+ <tcaption></tcaption></table>
+ <p>
+ <c>MAP_EXT</c> encodes a map. The <c>Arity</c> field is an unsigned
+ 4 byte integer in big endian format that determines the number of
+ key-value pairs in the map. Key and value pairs (<c>Ki => Vi</c>)
+ are encoded in the <c>Pairs</c> section in the following order:
+ <c>K1, V1, K2, V2,..., Kn, Vn</c>.
+ Duplicate keys are <em>not allowed</em> within the same map.
+ </p>
+ <p><em>Since: </em>OTP 17.0</p>
+ </section>
+
+ <section>
<marker id="NIL_EXT"/>
<title>NIL_EXT</title>
diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in
index 523130d01a..2a9a0a5c2f 100644
--- a/erts/emulator/Makefile.in
+++ b/erts/emulator/Makefile.in
@@ -414,13 +414,6 @@ else
UNIX_ONLY_BUILDS =
endif
-ifeq ($(TARGET), win32)
-TMPVAR := $(shell LANG=C $(PERL) utils/make_compiler_flags -o $(TTF_DIR)/erl_compile_flags.h -v CONFIG_H "N/A" -v CFLAGS "$(CFLAGS)" -v LDFLAGS "$(LDFLAGS)")
-else
-# We force this to be run every time this makefile is executed
-TMPVAR := $(shell LANG=C $(PERL) utils/make_compiler_flags -o $(TTF_DIR)/erl_compile_flags.h -f CONFIG_H "$(ERL_TOP)/erts/$(TARGET)/config.h" -v CFLAGS "$(CFLAGS)" -v LDFLAGS "$(LDFLAGS)")
-endif
-
.PHONY: all
ifdef VOID_EMULATOR
all:
@@ -499,6 +492,15 @@ release_docs_spec:
_create_dirs := $(shell mkdir -p $(CREATE_DIRS))
+
+# has to be run after _create_dirs
+ifeq ($(TARGET), win32)
+TMPVAR := $(shell LANG=C $(PERL) utils/make_compiler_flags -o $(TTF_DIR)/erl_compile_flags.h -v CONFIG_H "N/A" -v CFLAGS "$(CFLAGS)" -v LDFLAGS "$(LDFLAGS)")
+else
+# We force this to be run every time this makefile is executed
+TMPVAR := $(shell LANG=C $(PERL) utils/make_compiler_flags -o $(TTF_DIR)/erl_compile_flags.h -f CONFIG_H "$(ERL_TOP)/erts/$(TARGET)/config.h" -v CFLAGS "$(CFLAGS)" -v LDFLAGS "$(LDFLAGS)")
+endif
+
GENERATE =
HIPE_ASM =
@@ -1087,7 +1089,9 @@ BEAM_SRC=$(wildcard beam/*.c)
DRV_COMMON_SRC=$(wildcard drivers/common/*.c)
DRV_OSTYPE_SRC=$(wildcard drivers/$(ERLANG_OSTYPE)/*.c)
ALL_SYS_SRC=$(wildcard sys/$(ERLANG_OSTYPE)/*.c) $(wildcard sys/common/*.c)
-TARGET_SRC=$(wildcard $(TARGET)/*.c) $(wildcard $(TTF_DIR)/*.c)
+# We use $(shell ls) here instead of wildcard as $(wildcard ) resolved at
+# loadtime of the makefile and at that time these files are not generated yet.
+TARGET_SRC=$(shell ls $(TARGET)/*.c) $(shell ls $(TTF_DIR)/*.c)
# I do not want the -MG flag on windows, it does not work properly for a
# windows build.
diff --git a/erts/emulator/beam/dist.h b/erts/emulator/beam/dist.h
index 0519a9225e..f32b999198 100644
--- a/erts/emulator/beam/dist.h
+++ b/erts/emulator/beam/dist.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2013. All Rights Reserved.
+ * Copyright Ericsson AB 1996-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
@@ -40,6 +40,7 @@
#define DFLAG_SMALL_ATOM_TAGS 0x4000
#define DFLAG_INTERNAL_TAGS 0x8000
#define DFLAG_UTF8_ATOMS 0x10000
+#define DFLAG_MAP_TAG 0x20000
/* All flags that should be enabled when term_to_binary/1 is used. */
#define TERM_TO_BINARY_DFLAGS (DFLAG_EXTENDED_REFERENCES \
@@ -47,7 +48,8 @@
| DFLAG_NEW_FLOATS \
| DFLAG_EXTENDED_PIDS_PORTS \
| DFLAG_EXPORT_PTR_TAG \
- | DFLAG_BIT_BINARIES)
+ | DFLAG_BIT_BINARIES \
+ | DFLAG_MAP_TAG)
/* opcodes used in distribution messages */
#define DOP_LINK 1
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index 9671cde228..656de7c49a 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -2562,29 +2562,25 @@ enc_term_int(TTBEncodeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, byte* ep,
{
map_t *mp = (map_t*)map_val(obj);
Uint size = map_get_size(mp);
- Eterm *mptr;
*ep++ = MAP_EXT;
put_int32(size, ep); ep += 4;
- /* Push values first */
if (size > 0) {
- mptr = map_get_values(mp);
+ Eterm *kptr = map_get_keys(mp);
+ Eterm *vptr = map_get_values(mp);
+
for (i = size-1; i >= 1; i--) {
WSTACK_PUSH(s, ENC_TERM);
- WSTACK_PUSH(s, (UWord) mptr[i]);
+ WSTACK_PUSH(s, (UWord) vptr[i]);
+ WSTACK_PUSH(s, ENC_TERM);
+ WSTACK_PUSH(s, (UWord) kptr[i]);
}
WSTACK_PUSH(s, ENC_TERM);
- WSTACK_PUSH(s, (UWord) mptr[0]);
-
- mptr = map_get_keys(mp);
- for (i = size-1; i >= 1; i--) {
- WSTACK_PUSH(s, ENC_TERM);
- WSTACK_PUSH(s, (UWord) mptr[i]);
- }
+ WSTACK_PUSH(s, (UWord) vptr[0]);
- obj = mptr[0];
+ obj = kptr[0];
goto L_jump_start;
}
}
@@ -3518,16 +3514,16 @@ dec_term_atom_common:
keys = make_tuple(hp);
*hp++ = make_arityval(size);
- kptr = hp;
hp += size;
+ kptr = hp - 1;
mp = (map_t*)hp;
hp += MAP_HEADER_SIZE;
- vptr = hp;
hp += size;
+ vptr = hp - 1;
- /* kptr, first word for keys
- * vptr, first word for values
+ /* kptr, last word for keys
+ * vptr, last word for values
*/
/*
@@ -3542,27 +3538,12 @@ dec_term_atom_common:
mp->keys = keys;
*objp = make_map(mp);
- /* We assume the map is wellformed, meaning:
- * - ascending key order
- * - unique keys
- */
-
- objp = vptr + size - 1;
- n = size;
-
- while (n-- > 0) {
- *objp = (Eterm) COMPRESS_POINTER(next);
- next = objp;
- objp--;
- }
-
- objp = kptr + size - 1;
- n = size;
-
- while (n-- > 0) {
- *objp = (Eterm) COMPRESS_POINTER(next);
- next = objp;
- objp--;
+ for (n = size; n; n--) {
+ *vptr = (Eterm) COMPRESS_POINTER(next);
+ *kptr = (Eterm) COMPRESS_POINTER(vptr);
+ next = kptr;
+ vptr--;
+ kptr--;
}
}
break;
diff --git a/erts/emulator/test/map_SUITE.erl b/erts/emulator/test/map_SUITE.erl
index 753d6f7727..888ed8e272 100644
--- a/erts/emulator/test/map_SUITE.erl
+++ b/erts/emulator/test/map_SUITE.erl
@@ -813,16 +813,16 @@ t_map_encode_decode(Config) when is_list(Config) ->
%% literally #{ b=>2, a=>1 } in the internal order
#{ a:=1, b:=2 } =
- erlang:binary_to_term(<<131,116,0,0,0,2,100,0,1,98,100,0,1,97,97,2,97,1>>),
+ erlang:binary_to_term(<<131,116,0,0,0,2,100,0,1,98,97,2,100,0,1,97,97,1>>),
%% literally #{ "hi" => "value", a=>33, b=>55 } in the internal order
#{ a:=33, b:=55, "hi" := "value"} = erlang:binary_to_term(<<131,116,0,0,0,3,
107,0,2,104,105, % "hi" :: list()
- 100,0,1,97, % a :: atom()
- 100,0,1,98, % b :: atom()
107,0,5,118,97,108,117,101, % "value" :: list()
+ 100,0,1,97, % a :: atom()
97,33, % 33 :: integer()
+ 100,0,1,98, % b :: atom()
97,55 % 55 :: integer()
>>),
@@ -834,11 +834,17 @@ t_map_encode_decode(Config) when is_list(Config) ->
%% uniqueness violation
%% literally #{ a=>1, "hi"=>"value", a=>2 }
{'EXIT',{badarg,[{_,_,_,_}|_]}} = (catch
- erlang:binary_to_term(<<131,116,0,0,0,3,100,0,1,97,107,0,2,104,105,100,0,1,97,97,1,107,0,5,118,97,108,117,101,97,2>>)),
+ erlang:binary_to_term(<<131,116,0,0,0,3,
+ 100,0,1,97,
+ 97,1,
+ 107,0,2,104,105,
+ 107,0,5,118,97,108,117,101,
+ 100,0,1,97,
+ 97,2>>)),
%% bad size (too large)
{'EXIT',{badarg,[{_,_,_,_}|_]}} = (catch
- erlang:binary_to_term(<<131,116,0,0,0,12,100,0,1,97,100,0,1,98,97,1,97,1>>)),
+ erlang:binary_to_term(<<131,116,0,0,0,12,100,0,1,97,97,1,100,0,1,98,97,1>>)),
%% bad size (too small) .. should fail just truncate it .. weird.
%% possibly change external format so truncated will be #{a:=1}
@@ -852,7 +858,8 @@ map_encode_decode_and_match([{K,V}|Pairs], EncodedPairs, M0) ->
B0 = erlang:term_to_binary(M1),
Ls = lists:sort(fun(A,B) -> erts_internal:cmp_term(A,B) < 0 end, [{K, erlang:term_to_binary(K), erlang:term_to_binary(V)}|EncodedPairs]),
%% sort Ks and Vs according to term spec, then match it
- ok = match_encoded_map(B0, length(Ls), [Kbin||{_,Kbin,_}<-Ls] ++ [Vbin||{_,_,Vbin}<-Ls]),
+ KVbins = lists:foldr(fun({_,Kbin,Vbin}, Acc) -> [Kbin,Vbin | Acc] end, [], Ls),
+ ok = match_encoded_map(B0, length(Ls), KVbins),
%% decode and match it
M1 = erlang:binary_to_term(B0),
map_encode_decode_and_match(Pairs,Ls,M1);
diff --git a/lib/debugger/test/map_SUITE.erl b/lib/debugger/test/map_SUITE.erl
index e9f4ea1fad..741ad2dc41 100644
--- a/lib/debugger/test/map_SUITE.erl
+++ b/lib/debugger/test/map_SUITE.erl
@@ -790,16 +790,16 @@ t_map_encode_decode(Config) when is_list(Config) ->
%% literally #{ b=>2, a=>1 } in the internal order
#{ a:=1, b:=2 } =
- erlang:binary_to_term(<<131,116,0,0,0,2,100,0,1,98,100,0,1,97,97,2,97,1>>),
+ erlang:binary_to_term(<<131,116,0,0,0,2,100,0,1,98,97,2,100,0,1,97,97,1>>),
%% literally #{ "hi" => "value", a=>33, b=>55 } in the internal order
#{ a:=33, b:=55, "hi" := "value"} = erlang:binary_to_term(<<131,116,0,0,0,3,
107,0,2,104,105, % "hi" :: list()
- 100,0,1,97, % a :: atom()
- 100,0,1,98, % b :: atom()
107,0,5,118,97,108,117,101, % "value" :: list()
+ 100,0,1,97, % a :: atom()
97,33, % 33 :: integer()
+ 100,0,1,98, % b :: atom()
97,55 % 55 :: integer()
>>),
@@ -829,7 +829,8 @@ map_encode_decode_and_match([{K,V}|Pairs], EncodedPairs, M0) ->
B0 = erlang:term_to_binary(M1),
Ls = lists:sort(fun(A,B) -> erts_internal:cmp_term(A,B) < 0 end, [{K, erlang:term_to_binary(K), erlang:term_to_binary(V)}|EncodedPairs]),
%% sort Ks and Vs according to term spec, then match it
- ok = match_encoded_map(B0, length(Ls), [Kbin||{_,Kbin,_}<-Ls] ++ [Vbin||{_,_,Vbin}<-Ls]),
+ KVbins = lists:foldr(fun({_,Kbin,Vbin}, Acc) -> [Kbin,Vbin | Acc] end, [], Ls),
+ ok = match_encoded_map(B0, length(Ls), KVbins),
%% decode and match it
M1 = erlang:binary_to_term(B0),
map_encode_decode_and_match(Pairs,Ls,M1);
diff --git a/lib/erl_interface/doc/src/ei.xml b/lib/erl_interface/doc/src/ei.xml
index ab185c9179..90495eebd6 100644
--- a/lib/erl_interface/doc/src/ei.xml
+++ b/lib/erl_interface/doc/src/ei.xml
@@ -4,7 +4,7 @@
<cref>
<header>
<copyright>
- <year>2001</year><year>2013</year>
+ <year>2001</year><year>2014</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -417,6 +417,26 @@ ei_x_encode_empty_list(&amp;x);
</desc>
</func>
<func>
+ <name><ret>int</ret><nametext>ei_encode_map_header(char *buf, int *index, int arity)</nametext></name>
+ <name><ret>int</ret><nametext>ei_x_encode_map_header(ei_x_buff* x, int arity)</nametext></name>
+ <fsummary>Encode a map</fsummary>
+ <desc>
+ <p>This function encodes a map header, with a specified arity. The next
+ <c>arity*2</c> terms encoded will be the keys and values of the map
+ encoded in the following order: <c>K1, V1, K2, V2, ..., Kn, Vn</c>.
+ </p>
+ <p>E.g. to encode the map <c>#{a => "Apple", b => "Banana"}</c>:</p>
+ <pre>
+ei_x_encode_map_header(&amp;x, 2);
+ei_x_encode_atom(&amp;x, "a");
+ei_x_encode_string(&amp;x, "Apple");
+ei_x_encode_atom(&amp;x, "b");
+ei_x_encode_string(&amp;x, "Banana");
+ </pre>
+ <p>A correctly encoded map can not have duplicate keys.</p>
+ </desc>
+ </func>
+ <func>
<name><ret>int</ret><nametext>ei_get_type(const char *buf, const int *index, int *type, int *size)</nametext></name>
<fsummary>Fetch the type and size of an encoded term</fsummary>
<desc>
@@ -638,6 +658,18 @@ ei_x_encode_empty_list(&amp;x);
</desc>
</func>
<func>
+ <name><ret>int</ret><nametext>ei_decode_map_header(const char *buf, int *index, int *arity)</nametext></name>
+ <fsummary>Decode a map</fsummary>
+ <desc>
+ <p>This function decodes a map header from the binary
+ format. The number of key-value pairs is returned in
+ <c>*arity</c>. Keys and values follow in the following order:
+ <c>K1, V1, K2, V2, ..., Kn, Vn</c>. This makes a total of
+ <c>arity*2</c> terms. If <c>arity</c> is zero, it's an empty map.
+ A correctly encoded map does not have duplicate keys.</p>
+ </desc>
+ </func>
+ <func>
<name><ret>int</ret><nametext>ei_decode_ei_term(const char* buf, int* index, ei_term* term)</nametext></name>
<fsummary>Decode a term, without prior knowledge of type</fsummary>
<desc>
diff --git a/lib/erl_interface/include/ei.h b/lib/erl_interface/include/ei.h
index 9b83385a46..a3eb437f88 100644
--- a/lib/erl_interface/include/ei.h
+++ b/lib/erl_interface/include/ei.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2013. All Rights Reserved.
+ * Copyright Ericsson AB 1998-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
@@ -131,6 +131,7 @@
#define ERL_SMALL_BIG_EXT 'n'
#define ERL_LARGE_BIG_EXT 'o'
#define ERL_NEW_FUN_EXT 'p'
+#define ERL_MAP_EXT 't'
#define ERL_FUN_EXT 'u'
#define ERL_NEW_CACHE 'N' /* c nodes don't know these two */
@@ -467,6 +468,8 @@ int ei_encode_list_header(char *buf, int *index, int arity);
int ei_x_encode_list_header(ei_x_buff* x, long n);
#define ei_encode_empty_list(buf,i) ei_encode_list_header(buf,i,0)
int ei_x_encode_empty_list(ei_x_buff* x);
+int ei_encode_map_header(char *buf, int *index, int arity);
+int ei_x_encode_map_header(ei_x_buff* x, long n);
/*
* ei_get_type() returns the type and "size" of the item at
@@ -507,6 +510,7 @@ int ei_decode_term(const char *buf, int *index, void *t); /* ETERM** actually */
int ei_decode_trace(const char *buf, int *index, erlang_trace *p);
int ei_decode_tuple_header(const char *buf, int *index, int *arity);
int ei_decode_list_header(const char *buf, int *index, int *arity);
+int ei_decode_map_header(const char *buf, int *index, int *arity);
/*
* ei_decode_ei_term() returns 1 if term is decoded, 0 if term is OK,
diff --git a/lib/erl_interface/src/connect/ei_connect.c b/lib/erl_interface/src/connect/ei_connect.c
index c9aa28812c..3175d1bdfd 100644
--- a/lib/erl_interface/src/connect/ei_connect.c
+++ b/lib/erl_interface/src/connect/ei_connect.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2013. All Rights Reserved.
+ * Copyright Ericsson AB 2000-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
@@ -1336,7 +1336,8 @@ static int send_name_or_challenge(int fd, char *nodename,
| DFLAG_NEW_FUN_TAGS
| DFLAG_NEW_FLOATS
| DFLAG_SMALL_ATOM_TAGS
- | DFLAG_UTF8_ATOMS));
+ | DFLAG_UTF8_ATOMS
+ | DFLAG_MAP_TAG));
if (f_chall)
put32be(s, challenge);
memcpy(s, nodename, strlen(nodename));
diff --git a/lib/erl_interface/src/connect/ei_connect_int.h b/lib/erl_interface/src/connect/ei_connect_int.h
index 42ab9b58d7..8fab47a787 100644
--- a/lib/erl_interface/src/connect/ei_connect_int.h
+++ b/lib/erl_interface/src/connect/ei_connect_int.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2013. All Rights Reserved.
+ * Copyright Ericsson AB 2001-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
@@ -104,6 +104,7 @@ extern int h_errno;
#define DFLAG_NEW_FLOATS 0x800
#define DFLAG_SMALL_ATOM_TAGS 0x4000
#define DFLAG_UTF8_ATOMS 0x10000
+#define DFLAG_MAP_TAG 0x20000
ei_cnode *ei_fd_to_cnode(int fd);
int ei_distversion(int fd);
diff --git a/lib/erl_interface/src/decode/decode_skip.c b/lib/erl_interface/src/decode/decode_skip.c
index 553266471c..2260394da1 100644
--- a/lib/erl_interface/src/decode/decode_skip.c
+++ b/lib/erl_interface/src/decode/decode_skip.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2013. All Rights Reserved.
+ * Copyright Ericsson AB 2002-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
@@ -61,7 +61,13 @@ int ei_skip_term(const char* buf, int* index)
break;
case ERL_SMALL_TUPLE_EXT:
case ERL_LARGE_TUPLE_EXT:
- if (ei_decode_tuple_header(buf, index, &n) < 0) return -1;
+ if (ei_decode_tuple_header(buf, index, &n) < 0) return -1;
+ for (i = 0; i < n; ++i)
+ ei_skip_term(buf, index);
+ break;
+ case ERL_MAP_EXT:
+ if (ei_decode_map_header(buf, index, &n) < 0) return -1;
+ n *= 2;
for (i = 0; i < n; ++i)
ei_skip_term(buf, index);
break;
diff --git a/lib/erl_interface/src/decode/decode_tuple_header.c b/lib/erl_interface/src/decode/decode_tuple_header.c
index c0ba14ea47..698be1b97a 100644
--- a/lib/erl_interface/src/decode/decode_tuple_header.c
+++ b/lib/erl_interface/src/decode/decode_tuple_header.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1998-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
@@ -45,3 +45,24 @@ int ei_decode_tuple_header(const char *buf, int *index, int *arity)
return 0;
}
+
+int ei_decode_map_header(const char *buf, int *index, int *arity)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ int i;
+
+ switch ((i=get8(s))) {
+ case ERL_MAP_EXT:
+ if (arity) *arity = get32be(s);
+ else s += 4;
+ break;
+
+ default:
+ return -1;
+ }
+
+ *index += s-s0;
+
+ return 0;
+}
diff --git a/lib/erl_interface/src/encode/encode_tuple_header.c b/lib/erl_interface/src/encode/encode_tuple_header.c
index 97a3d1f808..5b11e60447 100644
--- a/lib/erl_interface/src/encode/encode_tuple_header.c
+++ b/lib/erl_interface/src/encode/encode_tuple_header.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1998-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
@@ -47,3 +47,20 @@ int ei_encode_tuple_header(char *buf, int *index, int arity)
return 0;
}
+int ei_encode_map_header(char *buf, int *index, int arity)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+
+ if (arity < 0) return -1;
+
+ if (!buf) s += 5;
+ else {
+ put8(s,ERL_MAP_EXT);
+ put32be(s,arity);
+ }
+
+ *index += s-s0;
+
+ return 0;
+}
diff --git a/lib/erl_interface/src/misc/ei_decode_term.c b/lib/erl_interface/src/misc/ei_decode_term.c
index ce5ae5b19d..2e7317f781 100644
--- a/lib/erl_interface/src/misc/ei_decode_term.c
+++ b/lib/erl_interface/src/misc/ei_decode_term.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2013. All Rights Reserved.
+ * Copyright Ericsson AB 2001-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
@@ -100,6 +100,7 @@ int ei_decode_ei_term(const char* buf, int* index, ei_term* term)
term->size = get16be(s);
return 0;
case ERL_LIST_EXT:
+ case ERL_MAP_EXT:
term->arity = get32be(s);
break;
case ERL_BINARY_EXT:
diff --git a/lib/erl_interface/src/misc/ei_x_encode.c b/lib/erl_interface/src/misc/ei_x_encode.c
index 14d0b56b8f..10542c88a5 100644
--- a/lib/erl_interface/src/misc/ei_x_encode.c
+++ b/lib/erl_interface/src/misc/ei_x_encode.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2013. All Rights Reserved.
+ * Copyright Ericsson AB 2001-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
@@ -206,6 +206,16 @@ int ei_x_encode_tuple_header(ei_x_buff* x, long n)
return ei_encode_tuple_header(x->buff, &x->index, n);
}
+int ei_x_encode_map_header(ei_x_buff* x, long n)
+{
+ int i = x->index;
+ if (ei_encode_map_header(NULL, &i, n) == -1)
+ return -1;
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_map_header(x->buff, &x->index, n);
+}
+
int ei_x_encode_atom(ei_x_buff* x, const char* s)
{
return ei_x_encode_atom_len_as(x, s, strlen(s), ERLANG_LATIN1, ERLANG_LATIN1);
diff --git a/lib/erl_interface/test/all_SUITE_data/ei_runner.c b/lib/erl_interface/test/all_SUITE_data/ei_runner.c
index cdf32b48c4..196a77dce5 100644
--- a/lib/erl_interface/test/all_SUITE_data/ei_runner.c
+++ b/lib/erl_interface/test/all_SUITE_data/ei_runner.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2001-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
@@ -182,6 +182,10 @@ char *read_packet(int *len)
return io_buf;
}
+void free_packet(char* packet)
+{
+ free(packet);
+}
/***********************************************************************
* S e n d i n g r e p l i e s
diff --git a/lib/erl_interface/test/all_SUITE_data/ei_runner.h b/lib/erl_interface/test/all_SUITE_data/ei_runner.h
index 96d6a1cbf7..a037341d57 100644
--- a/lib/erl_interface/test/all_SUITE_data/ei_runner.h
+++ b/lib/erl_interface/test/all_SUITE_data/ei_runner.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2001-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
@@ -44,6 +44,7 @@ void run_tests(char* argv0, TestCase cases[], unsigned number);
int get_bin_term(ei_x_buff* x, ei_term* term);
char *read_packet(int *len);
+void free_packet(char*);
/*
* Sending replies.
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE.erl b/lib/erl_interface/test/ei_decode_encode_SUITE.erl
index c7830f58f2..7caec6ac04 100644
--- a/lib/erl_interface/test/ei_decode_encode_SUITE.erl
+++ b/lib/erl_interface/test/ei_decode_encode_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2004-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
@@ -127,6 +127,15 @@ test_ei_decode_encode(Config) when is_list(Config) ->
send_rec(P, mk_ref({Atom,1}, [262143, 8723648, 24097245])),
void
end || Atom <- unicode_atom_data()],
+
+ send_rec(P, {}),
+ send_rec(P, {atom, Pid, Port, Ref}),
+ send_rec(P, [atom, Pid, Port, Ref]),
+ send_rec(P, [atom | Fun]),
+ send_rec(P, #{}),
+ send_rec(P, #{key => value}),
+ send_rec(P, maps:put(Port, Ref, #{key => value, key2 => Pid})),
+
?line runner:recv_eot(P),
ok.
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
index 317e5edecd..fcf546105b 100644
--- a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
+++ b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2013. All Rights Reserved.
+ * Copyright Ericsson AB 2004-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
@@ -32,9 +32,33 @@
/*#define MESSAGE(FMT,A1,A2) message(FMT,A1,A2)*/
#define MESSAGE(FMT,A1,A2)
-typedef int decodeFT(const char *buf, int *index, void*);
-typedef int encodeFT(char *buf, int *index, void*);
-typedef int x_encodeFT(ei_x_buff*, void*);
+
+typedef struct
+{
+ char name[MAXATOMLEN_UTF8];
+ erlang_char_encoding enc;
+}my_atom;
+
+struct my_obj {
+ union {
+ erlang_fun fun;
+ erlang_pid pid;
+ erlang_port port;
+ erlang_ref ref;
+ erlang_trace trace;
+ erlang_big big;
+ my_atom atom;
+
+ int arity;
+ }u;
+
+ int nterms; /* 0 for non-containers */
+ char* startp; /* container start position in decode buffer */
+};
+
+typedef int decodeFT(const char *buf, int *index, struct my_obj*);
+typedef int encodeFT(char *buf, int *index, struct my_obj*);
+typedef int x_encodeFT(ei_x_buff*, struct my_obj*);
struct Type {
char* name;
@@ -44,11 +68,36 @@ struct Type {
x_encodeFT* ei_x_encode_fp;
};
-typedef struct
-{
- char name[MAXATOMLEN_UTF8];
- erlang_char_encoding enc;
-}my_atom;
+
+struct Type fun_type = {
+ "fun", "erlang_fun", (decodeFT*)ei_decode_fun,
+ (encodeFT*)ei_encode_fun, (x_encodeFT*)ei_x_encode_fun
+};
+
+struct Type pid_type = {
+ "pid", "erlang_pid", (decodeFT*)ei_decode_pid,
+ (encodeFT*)ei_encode_pid, (x_encodeFT*)ei_x_encode_pid
+};
+
+struct Type port_type = {
+ "port", "erlang_port", (decodeFT*)ei_decode_port,
+ (encodeFT*)ei_encode_port, (x_encodeFT*)ei_x_encode_port
+};
+
+struct Type ref_type = {
+ "ref", "erlang_ref", (decodeFT*)ei_decode_ref,
+ (encodeFT*)ei_encode_ref, (x_encodeFT*)ei_x_encode_ref
+};
+
+struct Type trace_type = {
+ "trace", "erlang_trace", (decodeFT*)ei_decode_trace,
+ (encodeFT*)ei_encode_trace, (x_encodeFT*)ei_x_encode_trace
+};
+
+struct Type big_type = {
+ "big", "erlang_big", (decodeFT*)ei_decode_big,
+ (encodeFT*)ei_encode_big, (x_encodeFT*)ei_x_encode_big
+};
int ei_decode_my_atom(const char *buf, int *index, my_atom* a)
{
@@ -64,130 +113,274 @@ int ei_x_encode_my_atom(ei_x_buff* x, my_atom* a)
return ei_x_encode_atom_as(x, a->name, ERLANG_UTF8, a->enc);
}
+struct Type my_atom_type = {
+ "atom", "my_atom", (decodeFT*)ei_decode_my_atom,
+ (encodeFT*)ei_encode_my_atom, (x_encodeFT*)ei_x_encode_my_atom
+};
+
+
+int my_decode_tuple_header(const char *buf, int *index, struct my_obj* obj)
+{
+ int ret = ei_decode_tuple_header(buf, index, &obj->u.arity);
+ if (ret == 0 && obj)
+ obj->nterms = obj->u.arity;
+ return ret;
+}
+
+int my_encode_tuple_header(char *buf, int *index, struct my_obj* obj)
+{
+ return ei_encode_tuple_header(buf, index, obj->u.arity);
+}
+int my_x_encode_tuple_header(ei_x_buff* x, struct my_obj* obj)
+{
+ return ei_x_encode_tuple_header(x, (long)obj->u.arity);
+}
+
+struct Type tuple_type = {
+ "tuple_header", "arity", my_decode_tuple_header,
+ my_encode_tuple_header, my_x_encode_tuple_header
+};
+
+
+int my_decode_list_header(const char *buf, int *index, struct my_obj* obj)
+{
+ int ret = ei_decode_list_header(buf, index, &obj->u.arity);
+ if (ret == 0 && obj) {
+ obj->nterms = obj->u.arity + 1;
+ }
+ return ret;
+}
+int my_encode_list_header(char *buf, int *index, struct my_obj* obj)
+{
+ return ei_encode_list_header(buf, index, obj->u.arity);
+}
+int my_x_encode_list_header(ei_x_buff* x, struct my_obj* obj)
+{
+ return ei_x_encode_list_header(x, (long)obj->u.arity);
+}
+
+struct Type list_type = {
+ "list_header", "arity", my_decode_list_header,
+ my_encode_list_header, my_x_encode_list_header
+};
+
+
+int my_decode_nil(const char *buf, int *index, struct my_obj* dummy)
+{
+ int type, size, ret;
+ ret = ei_get_type(buf, index, &type, &size);
+ (*index)++;
+ return ret ? ret : !(type == ERL_NIL_EXT);
+
+}
+int my_encode_nil(char *buf, int *index, struct my_obj* dummy)
+{
+ return ei_encode_empty_list(buf, index);
+}
+
+int my_x_encode_nil(ei_x_buff* x, struct my_obj* dummy)
+{
+ return ei_x_encode_empty_list(x);
+}
+
+struct Type nil_type = {
+ "empty_list", "nil", my_decode_nil,
+ my_encode_nil, my_x_encode_nil
+};
+
+int my_decode_map_header(const char *buf, int *index, struct my_obj* obj)
+{
+ int ret = ei_decode_map_header(buf, index, &obj->u.arity);
+ if (ret == 0 && obj)
+ obj->nterms = obj->u.arity * 2;
+ return ret;
+}
+int my_encode_map_header(char *buf, int *index, struct my_obj* obj)
+{
+ return ei_encode_map_header(buf, index, obj->u.arity);
+}
+int my_x_encode_map_header(ei_x_buff* x, struct my_obj* obj)
+{
+ return ei_x_encode_map_header(x, (long)obj->u.arity);
+}
+
+struct Type map_type = {
+ "map_header", "arity", my_decode_map_header,
+ my_encode_map_header, my_x_encode_map_header
+};
+
+
#define BUFSZ 2000
-void decode_encode(struct Type* t, void* obj)
+void decode_encode(struct Type** tv, int nobj)
{
- char *buf;
- char buf2[BUFSZ];
- int size1 = 0;
- int size2 = 0;
- int size3 = 0;
- int err;
+ struct my_obj objv[10];
+ int oix = 0;
+ char* packet;
+ char* inp;
+ char* outp;
+ char out_buf[BUFSZ];
+ int size1, size2, size3;
+ int err, i;
ei_x_buff arg;
- MESSAGE("ei_decode_%s, arg is type %s", t->name, t->type);
- buf = read_packet(NULL);
- err = t->ei_decode_fp(buf+1, &size1, NULL);
- if (err != 0) {
- if (err != -1) {
- fail("decode returned non zero but not -1");
- } else {
- fail("decode returned non zero");
+ packet = read_packet(NULL);
+ inp = packet+1;
+ outp = out_buf;
+ ei_x_new(&arg);
+ for (i=0; i<nobj; i++) {
+ struct Type* t = tv[i];
+
+ MESSAGE("ei_decode_%s, arg is type %s", t->name, t->type);
+
+ size1 = 0;
+ err = t->ei_decode_fp(inp, &size1, NULL);
+ if (err != 0) {
+ if (err != -1) {
+ fail("decode returned non zero but not -1");
+ } else {
+ fail("decode returned non zero");
+ }
+ return;
+ }
+ if (size1 < 1) {
+ fail("size is < 1");
+ return;
}
- return;
- }
- if (size1 < 1) {
- fail("size is < 1");
- return;
- }
- if (size1 > BUFSZ) {
- fail("size is > BUFSZ");
- return;
- }
+ if (size1 > BUFSZ) {
+ fail("size is > BUFSZ");
+ return;
+ }
- err = t->ei_decode_fp(buf+1, &size2, obj);
- if (err != 0) {
- if (err != -1) {
- fail("decode returned non zero but not -1");
- } else {
- fail("decode returned non zero");
+ size2 = 0;
+ objv[oix].nterms = 0;
+ objv[oix].startp = inp;
+ err = t->ei_decode_fp(inp, &size2, &objv[oix]);
+ if (err != 0) {
+ if (err != -1) {
+ fail("decode returned non zero but not -1");
+ } else {
+ fail("decode returned non zero");
+ }
+ return;
+ }
+ if (size1 != size2) {
+ MESSAGE("size1 = %d, size2 = %d\n",size1,size2);
+ fail("decode sizes differs");
+ return;
}
- return;
- }
- if (size1 != size2) {
- MESSAGE("size1 = %d, size2 = %d\n",size1,size2);
- fail("decode sizes differs");
- return;
- }
- size2 = 0;
- err = ei_skip_term(buf+1, &size2);
- if (err != 0) {
- fail("ei_skip_term returned non zero");
- return;
- }
- if (size1 != size2) {
- MESSAGE("size1 = %d, size2 = %d\n",size1,size2);
- fail("skip size differs");
- return;
- }
+ if (!objv[oix].nterms) {
+ size2 = 0;
+ err = ei_skip_term(inp, &size2);
+ if (err != 0) {
+ fail("ei_skip_term returned non zero");
+ return;
+ }
+ if (size1 != size2) {
+ MESSAGE("size1 = %d, size2 = %d\n",size1,size2);
+ fail("skip size differs");
+ return;
+ }
+ }
- MESSAGE("ei_encode_%s buf is NULL, arg is type %s", t->name, t->type);
- size2 = 0;
- err = t->ei_encode_fp(NULL, &size2, obj);
- if (err != 0) {
- if (err != -1) {
- fail("size calculation returned non zero but not -1");
+ MESSAGE("ei_encode_%s buf is NULL, arg is type %s", t->name, t->type);
+ size2 = 0;
+ err = t->ei_encode_fp(NULL, &size2, &objv[oix]);
+ if (err != 0) {
+ if (err != -1) {
+ fail("size calculation returned non zero but not -1");
+ return;
+ } else {
+ fail("size calculation returned non zero");
+ return;
+ }
+ }
+ if (size1 != size2) {
+ MESSAGE("size1 = %d, size2 = %d\n",size1,size2);
+ fail("decode and encode size differs when buf is NULL");
return;
- } else {
- fail("size calculation returned non zero");
+ }
+ MESSAGE("ei_encode_%s, arg is type %s", t->name, t->type);
+ size3 = 0;
+ err = t->ei_encode_fp(outp, &size3, &objv[oix]);
+ if (err != 0) {
+ if (err != -1) {
+ fail("returned non zero but not -1");
+ } else {
+ fail("returned non zero");
+ }
return;
}
- }
- if (size1 != size2) {
- MESSAGE("size1 = %d, size2 = %d\n",size1,size2);
- fail("decode and encode size differs when buf is NULL");
- return;
- }
- MESSAGE("ei_encode_%s, arg is type %s", t->name, t->type);
- err = t->ei_encode_fp(buf2, &size3, obj);
- if (err != 0) {
- if (err != -1) {
- fail("returned non zero but not -1");
- } else {
- fail("returned non zero");
+ if (size1 != size3) {
+ MESSAGE("size1 = %d, size2 = %d\n",size1,size3);
+ fail("decode and encode size differs");
+ return;
}
- return;
- }
- if (size1 != size3) {
- MESSAGE("size1 = %d, size2 = %d\n",size1,size3);
- fail("decode and encode size differs");
- return;
- }
- send_buffer(buf2, size1);
- MESSAGE("ei_x_encode_%s, arg is type %s", t->name, t->type);
- ei_x_new(&arg);
- err = t->ei_x_encode_fp(&arg, obj);
- if (err != 0) {
- if (err != -1) {
- fail("returned non zero but not -1");
- } else {
- fail("returned non zero");
+ MESSAGE("ei_x_encode_%s, arg is type %s", t->name, t->type);
+ err = t->ei_x_encode_fp(&arg, &objv[oix]);
+ if (err != 0) {
+ if (err != -1) {
+ fail("returned non zero but not -1");
+ } else {
+ fail("returned non zero");
+ }
+ ei_x_free(&arg);
+ return;
}
- ei_x_free(&arg);
- return;
+ if (arg.index < 1) {
+ fail("size is < 1");
+ ei_x_free(&arg);
+ return;
+ }
+
+ inp += size1;
+ outp += size1;
+
+ if (objv[oix].nterms) { /* container term */
+ if (++oix >= sizeof(objv)/sizeof(*objv))
+ fail("Term too deep");
+ }
+ else { /* "leaf" term */
+ while (oix > 0) {
+ if (--(objv[oix - 1].nterms) == 0) {
+ /* last element in container */
+ --oix;
+
+ size2 = 0;
+ err = ei_skip_term(objv[oix].startp, &size2);
+ if (err != 0) {
+ fail("ei_skip_term returned non zero");
+ return;
+ }
+ if (objv[oix].startp + size2 != inp) {
+ MESSAGE("size1 = %d, size2 = %d\n", size1, size2);
+ fail("container skip size differs");
+ return;
+ }
+ }
+ else
+ break; /* more elements in container */
+ }
+ }
+
}
- if (arg.index < 1) {
- fail("size is < 1");
- ei_x_free(&arg);
- return;
+ if (oix > 0) {
+ fail("Container not complete");
}
+ send_buffer(out_buf, outp - out_buf);
send_buffer(arg.buff, arg.index);
ei_x_free(&arg);
+ free_packet(packet);
}
+void decode_encode_one(struct Type* t)
+{
+ decode_encode(&t, 1);
+}
-#define EI_DECODE_ENCODE(TYPE, ERLANG_TYPE) { \
- struct Type type_struct = {#TYPE, #ERLANG_TYPE, \
- (decodeFT*)ei_decode_##TYPE, \
- (encodeFT*)ei_encode_##TYPE, \
- (x_encodeFT*)ei_x_encode_##TYPE }; \
- ERLANG_TYPE type_obj; \
- decode_encode(&type_struct, &type_obj); \
- }
void decode_encode_big(struct Type* t)
@@ -274,14 +467,6 @@ void decode_encode_big(struct Type* t)
ei_free_big(p);
}
-#define EI_DECODE_ENCODE_BIG(TYPE, ERLANG_TYPE) { \
- struct Type type_struct = {#TYPE, #ERLANG_TYPE, \
- (decodeFT*)ei_decode_##TYPE, \
- (encodeFT*)ei_encode_##TYPE, \
- (x_encodeFT*)ei_x_encode_##TYPE }; \
- decode_encode_big(&type_struct); \
- }
-
/* ******************************************************************** */
@@ -290,34 +475,63 @@ TESTCASE(test_ei_decode_encode)
{
int i;
- EI_DECODE_ENCODE(fun , erlang_fun);
- EI_DECODE_ENCODE(pid , erlang_pid);
- EI_DECODE_ENCODE(port , erlang_port);
- EI_DECODE_ENCODE(ref , erlang_ref);
- EI_DECODE_ENCODE(trace, erlang_trace);
+ decode_encode_one(&fun_type);
+ decode_encode_one(&pid_type);
+ decode_encode_one(&port_type);
+ decode_encode_one(&ref_type);
+ decode_encode_one(&trace_type);
- EI_DECODE_ENCODE_BIG(big , erlang_big);
- EI_DECODE_ENCODE_BIG(big , erlang_big);
- EI_DECODE_ENCODE_BIG(big , erlang_big);
+ decode_encode_big(&big_type);
+ decode_encode_big(&big_type);
+ decode_encode_big(&big_type);
- EI_DECODE_ENCODE_BIG(big , erlang_big);
- EI_DECODE_ENCODE_BIG(big , erlang_big);
- EI_DECODE_ENCODE_BIG(big , erlang_big);
+ decode_encode_big(&big_type);
+ decode_encode_big(&big_type);
+ decode_encode_big(&big_type);
/* Test large node containers... */
- EI_DECODE_ENCODE(pid , erlang_pid);
- EI_DECODE_ENCODE(port , erlang_port);
- EI_DECODE_ENCODE(ref , erlang_ref);
- EI_DECODE_ENCODE(pid , erlang_pid);
- EI_DECODE_ENCODE(port , erlang_port);
- EI_DECODE_ENCODE(ref , erlang_ref);
+ decode_encode_one(&pid_type);
+ decode_encode_one(&port_type);
+ decode_encode_one(&ref_type);
+ decode_encode_one(&pid_type);
+ decode_encode_one(&port_type);
+ decode_encode_one(&ref_type);
/* Unicode atoms */
for (i=0; i<24; i++) {
- EI_DECODE_ENCODE(my_atom, my_atom);
- EI_DECODE_ENCODE(pid, erlang_pid);
- EI_DECODE_ENCODE(port, erlang_port);
- EI_DECODE_ENCODE(ref, erlang_ref);
+ decode_encode_one(&my_atom_type);
+ decode_encode_one(&pid_type);
+ decode_encode_one(&port_type);
+ decode_encode_one(&ref_type);
+ }
+
+ decode_encode_one(&tuple_type); /* {} */
+ {
+ struct Type* tpl[] = { &tuple_type, &my_atom_type, &pid_type, &port_type, &ref_type };
+ decode_encode(tpl, 5);
+ }
+
+ {
+ struct Type* list[] = { &list_type, &my_atom_type, &pid_type, &port_type, &ref_type, &nil_type };
+ decode_encode(list, 6);
+ }
+ {
+ struct Type* list[] = { &list_type, &my_atom_type, &fun_type };
+ decode_encode(list, 3);
+ }
+ decode_encode_one(&map_type); /* #{} */
+ { /* #{atom => atom}*/
+ struct Type* map[] = { &map_type, &my_atom_type, &my_atom_type };
+ decode_encode(map, 3);
+ }
+
+ { /* #{atom => atom, atom => pid, port => ref }*/
+ struct Type* map[] = { &map_type,
+ &my_atom_type, &my_atom_type,
+ &my_atom_type, &pid_type,
+ &port_type, &ref_type
+ };
+ decode_encode(map, 7);
}
report(1);
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractNode.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractNode.java
index 968f284bff..3ef44b8851 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractNode.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractNode.java
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2013. All Rights Reserved.
+ * Copyright Ericsson AB 2000-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
@@ -92,6 +92,7 @@ public class AbstractNode {
static final int dFlagNewFloats = 0x800;
static final int dFlagUnicodeIo = 0x1000;
static final int dFlagUtf8Atoms = 0x10000;
+ static final int dFlagMapTag = 0x20000;
int ntype = NTYPE_R6;
int proto = 0; // tcp/ip
@@ -100,7 +101,7 @@ public class AbstractNode {
int creation = 0;
int flags = dFlagExtendedReferences | dFlagExtendedPidsPorts
| dFlagBitBinaries | dFlagNewFloats | dFlagFunTags
- | dflagNewFunTags | dFlagUtf8Atoms;
+ | dflagNewFunTags | dFlagUtf8Atoms | dFlagMapTag;
/* initialize hostname and default cookie */
static {
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangMap.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangMap.java
index 7c1cf84e98..03c18e55a2 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangMap.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangMap.java
@@ -125,8 +125,6 @@ public class OtpErlangMap extends OtpErlangObject implements Serializable,
for (int i = 0; i < arity; i++) {
keys[i] = buf.read_any();
- }
- for (int i = 0; i < arity; i++) {
values[i] = buf.read_any();
}
} else {
@@ -227,8 +225,6 @@ public class OtpErlangMap extends OtpErlangObject implements Serializable,
for (int i = 0; i < arity; i++) {
buf.write_any(keys[i]);
- }
- for (int i = 0; i < arity; i++) {
buf.write_any(values[i]);
}
}
diff --git a/lib/jinterface/test/jinterface_SUITE_data/Maps.java b/lib/jinterface/test/jinterface_SUITE_data/Maps.java
index 136a665f23..653defc621 100644
--- a/lib/jinterface/test/jinterface_SUITE_data/Maps.java
+++ b/lib/jinterface/test/jinterface_SUITE_data/Maps.java
@@ -42,16 +42,16 @@ class Maps {
runTest(new byte[] { (byte) 131, 116, 0, 0, 0, 1, 100, 0, 1, 97, 100,
0, 1, 98 }, "#{a => b}", 2);
// make sure keys are sorted here, jinterface doesn't reorder them
- runTest(new byte[] { (byte) 131, 116, 0, 0, 0, 2, 97, 2, 100, 0, 1, 97,
- 106, 97, 1 }, "#{2 => [],a => 1}", 3);
+ runTest(new byte[] { (byte) 131, 116, 0, 0, 0, 2, 97, 2, 106,
+ 100, 0, 1, 97, 97, 1 }, "#{2 => [],a => 1}", 3);
runTest(new byte[] { (byte) 131, 116, 0, 0, 0, 1, 104, 1, 97, 3, 108,
0, 0, 0, 1, 100, 0, 1, 114, 106 }, "#{{3} => [r]}", 4);
try {
// #{2 => [],a => 1}
final OtpErlangMap map = new OtpErlangMap(new OtpInputStream(
- new byte[] { (byte) 131, 116, 0, 0, 0, 2, 97, 2, 100, 0, 1,
- 97, 106, 97, 1 }));
+ new byte[] { (byte) 131, 116, 0, 0, 0, 2, 97, 2, 106,
+ 100, 0, 1, 97, 97, 1 }));
if (map.arity() != 2) {
fail(5);
diff --git a/lib/kernel/include/dist.hrl b/lib/kernel/include/dist.hrl
index e32c112e63..77556d1303 100644
--- a/lib/kernel/include/dist.hrl
+++ b/lib/kernel/include/dist.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1999-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
@@ -37,3 +37,4 @@
-define(DFLAG_DIST_HDR_ATOM_CACHE,16#2000).
-define(DFLAG_SMALL_ATOM_TAGS, 16#4000).
-define(DFLAG_UTF8_ATOMS, 16#10000).
+-define(DFLAG_MAP_TAG, 16#20000).
diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl
index fc50ec6717..b127fe2e33 100644
--- a/lib/kernel/src/dist_util.erl
+++ b/lib/kernel/src/dist_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1999-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
@@ -116,7 +116,8 @@ make_this_flags(RequestType, OtherNode) ->
?DFLAG_UNICODE_IO bor
?DFLAG_DIST_HDR_ATOM_CACHE bor
?DFLAG_SMALL_ATOM_TAGS bor
- ?DFLAG_UTF8_ATOMS).
+ ?DFLAG_UTF8_ATOMS bor
+ ?DFLAG_MAP_TAG).
handshake_other_started(#hs_data{request_type=ReqType}=HSData0) ->
{PreOtherFlags,Node,Version} = recv_name(HSData0),