From caeea720b52252bc37f1e60bf546333bfe3c2cf8 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 5 Mar 2014 20:24:35 +0100 Subject: erl_interface: refactor ei_decode_encode_test.c to prepare for lists, tuples and ... maps! --- .../ei_decode_encode_test.c | 345 ++++++++++++--------- 1 file changed, 207 insertions(+), 138 deletions(-) (limited to 'lib') 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..3e32be8087 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 @@ -32,9 +32,28 @@ /*#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; + +union my_obj { + erlang_fun fun; + erlang_pid pid; + erlang_port port; + erlang_ref ref; + erlang_trace trace; + erlang_big big; + my_atom atom; + + int arity; +}; + +typedef int decodeFT(const char *buf, int *index, union my_obj*); +typedef int encodeFT(char *buf, int *index, union my_obj*); +typedef int x_encodeFT(ei_x_buff*, union my_obj*); struct Type { char* name; @@ -44,11 +63,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 +108,163 @@ 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_encode_tuple_header(char *buf, int *index, union my_obj* obj) +{ + return ei_encode_tuple_header(buf, index, obj->arity); +} +int my_x_encode_tuple_header(ei_x_buff* x, union my_obj* obj) +{ + return ei_x_encode_tuple_header(x, (long)obj->arity); +} + +struct Type tuple_type = { + "tuple_header", "arity", (decodeFT*)ei_decode_tuple_header, + my_encode_tuple_header, my_x_encode_tuple_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; + union my_obj obj; + 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; iname, 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; + err = t->ei_decode_fp(inp, &size2, &obj); + 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 (t != &tuple_type) { + 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, &obj); + 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, &obj); + 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, &obj); + 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; + if (arg.index < 1) { + fail("size is < 1"); + ei_x_free(&arg); + return; + } + + inp += size1; + outp += size1; } + send_buffer(out_buf, outp - out_buf); send_buffer(arg.buff, arg.index); ei_x_free(&arg); + free(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 +351,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 +359,34 @@ 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); } report(1); -- cgit v1.2.3 From 453cba0046ec8363a4c3cea97ce22a6f4ff0b75a Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 6 Mar 2014 12:25:05 +0100 Subject: erl_interface: test decode_encode of tuples and lists --- lib/erl_interface/test/ei_decode_encode_SUITE.erl | 7 ++- .../ei_decode_encode_test.c | 59 +++++++++++++++++++++- 2 files changed, 63 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE.erl b/lib/erl_interface/test/ei_decode_encode_SUITE.erl index c7830f58f2..b0952d4b04 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,11 @@ 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]), ?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 3e32be8087..9a50aef7b6 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 @@ -128,6 +128,45 @@ struct Type tuple_type = { my_encode_tuple_header, my_x_encode_tuple_header }; +int my_encode_list_header(char *buf, int *index, union my_obj* obj) +{ + return ei_encode_list_header(buf, index, obj->arity); +} +int my_x_encode_list_header(ei_x_buff* x, union my_obj* obj) +{ + return ei_x_encode_list_header(x, (long)obj->arity); +} + +struct Type list_type = { + "list_header", "arity", (decodeFT*)ei_decode_list_header, + my_encode_list_header, my_x_encode_list_header +}; + + +int my_decode_nil(const char *buf, int *index, union 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, union my_obj* dummy) +{ + return ei_encode_empty_list(buf, index); +} + +int my_x_encode_nil(ei_x_buff* x, union my_obj* dummy) +{ + return ei_x_encode_empty_list(x); +} + +struct Type nil_type = { + "empty_list", "nil", (decodeFT*)my_decode_nil, + my_encode_nil, my_x_encode_nil +}; + + #define BUFSZ 2000 void decode_encode(struct Type** tv, int nobj) @@ -186,7 +225,7 @@ void decode_encode(struct Type** tv, int nobj) return; } - if (t != &tuple_type) { + if (t != &tuple_type && t != &list_type) { size2 = 0; err = ei_skip_term(inp, &size2); if (err != 0) { @@ -389,6 +428,22 @@ TESTCASE(test_ei_decode_encode) 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); + } + + report(1); } -- cgit v1.2.3 From 6941af88ad016141f568279f065cb181074f1f9f Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 6 Mar 2014 15:13:34 +0100 Subject: erl_interface: Add ei encode/decode for maps --- lib/erl_interface/doc/src/ei.xml | 36 +++++++++++++++++++++- lib/erl_interface/include/ei.h | 6 +++- lib/erl_interface/src/decode/decode_tuple_header.c | 23 +++++++++++++- lib/erl_interface/src/encode/encode_tuple_header.c | 19 +++++++++++- lib/erl_interface/src/misc/ei_decode_term.c | 3 +- lib/erl_interface/src/misc/ei_x_encode.c | 12 +++++++- 6 files changed, 93 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/erl_interface/doc/src/ei.xml b/lib/erl_interface/doc/src/ei.xml index ab185c9179..1756ee8a7d 100644 --- a/lib/erl_interface/doc/src/ei.xml +++ b/lib/erl_interface/doc/src/ei.xml @@ -4,7 +4,7 @@
- 20012013 + 20012014 Ericsson AB. All Rights Reserved. @@ -416,6 +416,27 @@ ei_x_encode_empty_list(&x); tail of a list.

+ + intei_encode_map_header(char *buf, int *index, int arity) + intei_x_encode_map_header(ei_x_buff* x, int arity) + Encode a map + +

This function encodes a map header, with a specified arity. The next + arity terms encoded will be the keys of the map, and the next + arity terms after that will be the corresponding values in + same order.

+

E.g. to encode the map #{a => "Apple", b => "Banana"}:

+
+ei_x_encode_map_header(&x, 2);
+ei_x_encode_atom(&x, "a");
+ei_x_encode_atom(&x, "b");
+ei_x_encode_string(&x, "Apple");
+ei_x_encode_string(&x, "Banana");
+        
+

A correctly encoded map can not have duplicate keys, but no check + for duplicate keys is done by this function.

+
+
intei_get_type(const char *buf, const int *index, int *type, int *size) Fetch the type and size of an encoded term @@ -637,6 +658,19 @@ ei_x_encode_empty_list(&x); instead.

+ + intei_decode_map_header(const char *buf, int *index, int *arity) + Decode a map + +

This function decodes a map header from the binary + format. The number of key-value pairs is returned in + arity. Keys and values follows, first all keys and then all values, + which makes a total of arity*2 terms. + Keys and values are paired according to their order, the first key + with the first value and so on. If arity is zero, it's an empty map. + A correctly encoded map does not have duplicate keys.

+
+
intei_decode_ei_term(const char* buf, int* index, ei_term* term) Decode a term, without prior knowledge of type 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/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); -- cgit v1.2.3 From 78796d03ac341da53e9c8b7f8d69cc3c0a949c14 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 6 Mar 2014 16:17:09 +0100 Subject: erl_interface: test decode/encode of maps --- lib/erl_interface/test/ei_decode_encode_SUITE.erl | 4 ++++ .../ei_decode_encode_test.c | 28 +++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE.erl b/lib/erl_interface/test/ei_decode_encode_SUITE.erl index b0952d4b04..7caec6ac04 100644 --- a/lib/erl_interface/test/ei_decode_encode_SUITE.erl +++ b/lib/erl_interface/test/ei_decode_encode_SUITE.erl @@ -132,6 +132,10 @@ test_ei_decode_encode(Config) when is_list(Config) -> 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 9a50aef7b6..1ef17d4161 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 @@ -166,6 +166,20 @@ struct Type nil_type = { my_encode_nil, my_x_encode_nil }; +int my_encode_map_header(char *buf, int *index, union my_obj* obj) +{ + return ei_encode_map_header(buf, index, obj->arity); +} +int my_x_encode_map_header(ei_x_buff* x, union my_obj* obj) +{ + return ei_x_encode_map_header(x, (long)obj->arity); +} + +struct Type map_type = { + "map_header", "arity", (decodeFT*)ei_decode_map_header, + my_encode_map_header, my_x_encode_map_header +}; + #define BUFSZ 2000 @@ -225,7 +239,7 @@ void decode_encode(struct Type** tv, int nobj) return; } - if (t != &tuple_type && t != &list_type) { + if (t != &tuple_type && t != &list_type && t != &map_type) { size2 = 0; err = ei_skip_term(inp, &size2); if (err != 0) { @@ -442,7 +456,19 @@ TESTCASE(test_ei_decode_encode) 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, &port_type, + &my_atom_type, &pid_type, &ref_type + }; + decode_encode(map, 7); + } report(1); } -- cgit v1.2.3 From dbdf33a57b8e92fc9a45029ed3fef0f70c852909 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 10 Mar 2014 20:19:58 +0100 Subject: erl_interface: Fix mem leak in ei_decode_encode_test --- lib/erl_interface/test/all_SUITE_data/ei_runner.c | 6 +++++- lib/erl_interface/test/all_SUITE_data/ei_runner.h | 3 ++- .../test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'lib') 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_data/ei_decode_encode_test.c b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c index 1ef17d4161..649138b471 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 @@ -310,7 +310,7 @@ void decode_encode(struct Type** tv, int nobj) send_buffer(out_buf, outp - out_buf); send_buffer(arg.buff, arg.index); ei_x_free(&arg); - free(packet); + free_packet(packet); } void decode_encode_one(struct Type* t) -- cgit v1.2.3 From e5f5346c5c6d7cd7f5c68b523970c542bccd9aff Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 10 Mar 2014 20:21:08 +0100 Subject: erl_interface: Add map support in ei_skip_term --- lib/erl_interface/src/decode/decode_skip.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'lib') 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; -- cgit v1.2.3 From 726271d2307c2987c06075253646875815719733 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 10 Mar 2014 20:30:11 +0100 Subject: erl_interface: Add test for ei_skip_term of container terms --- .../ei_decode_encode_test.c | 139 +++++++++++++++------ 1 file changed, 101 insertions(+), 38 deletions(-) (limited to 'lib') 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 649138b471..790d498a1d 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 @@ -39,21 +39,26 @@ typedef struct erlang_char_encoding enc; }my_atom; -union my_obj { - erlang_fun fun; - erlang_pid pid; - erlang_port port; - erlang_ref ref; - erlang_trace trace; - erlang_big big; - my_atom atom; - - int arity; +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, union my_obj*); -typedef int encodeFT(char *buf, int *index, union my_obj*); -typedef int x_encodeFT(ei_x_buff*, union my_obj*); +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; @@ -114,36 +119,53 @@ struct Type my_atom_type = { }; -int my_encode_tuple_header(char *buf, int *index, union my_obj* obj) +int my_decode_tuple_header(const char *buf, int *index, struct my_obj* obj) { - return ei_encode_tuple_header(buf, index, obj->arity); + int ret = ei_decode_tuple_header(buf, index, &obj->u.arity); + if (ret == 0 && obj) + obj->nterms = obj->u.arity; + return ret; } -int my_x_encode_tuple_header(ei_x_buff* x, union my_obj* obj) + +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->arity); + return ei_x_encode_tuple_header(x, (long)obj->u.arity); } struct Type tuple_type = { - "tuple_header", "arity", (decodeFT*)ei_decode_tuple_header, + "tuple_header", "arity", my_decode_tuple_header, my_encode_tuple_header, my_x_encode_tuple_header }; -int my_encode_list_header(char *buf, int *index, union my_obj* obj) + +int my_decode_list_header(const char *buf, int *index, struct my_obj* obj) { - return ei_encode_list_header(buf, index, obj->arity); + 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, union my_obj* obj) +int my_x_encode_list_header(ei_x_buff* x, struct my_obj* obj) { - return ei_x_encode_list_header(x, (long)obj->arity); + return ei_x_encode_list_header(x, (long)obj->u.arity); } struct Type list_type = { - "list_header", "arity", (decodeFT*)ei_decode_list_header, + "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, union my_obj* dummy) +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); @@ -151,32 +173,39 @@ int my_decode_nil(const char *buf, int *index, union my_obj* dummy) return ret ? ret : !(type == ERL_NIL_EXT); } -int my_encode_nil(char *buf, int *index, union my_obj* dummy) +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, union my_obj* dummy) +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", (decodeFT*)my_decode_nil, + "empty_list", "nil", my_decode_nil, my_encode_nil, my_x_encode_nil }; -int my_encode_map_header(char *buf, int *index, union my_obj* obj) +int my_decode_map_header(const char *buf, int *index, struct my_obj* obj) { - return ei_encode_map_header(buf, index, obj->arity); + 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_x_encode_map_header(ei_x_buff* x, union my_obj* obj) +int my_encode_map_header(char *buf, int *index, struct my_obj* obj) { - return ei_x_encode_map_header(x, (long)obj->arity); + 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", (decodeFT*)ei_decode_map_header, + "map_header", "arity", my_decode_map_header, my_encode_map_header, my_x_encode_map_header }; @@ -185,7 +214,8 @@ struct Type map_type = { void decode_encode(struct Type** tv, int nobj) { - union my_obj obj; + struct my_obj objv[10]; + int oix = 0; char* packet; char* inp; char* outp; @@ -224,7 +254,9 @@ void decode_encode(struct Type** tv, int nobj) } size2 = 0; - err = t->ei_decode_fp(inp, &size2, &obj); + 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"); @@ -239,7 +271,7 @@ void decode_encode(struct Type** tv, int nobj) return; } - if (t != &tuple_type && t != &list_type && t != &map_type) { + if (!objv[oix].nterms) { size2 = 0; err = ei_skip_term(inp, &size2); if (err != 0) { @@ -255,7 +287,7 @@ void decode_encode(struct Type** tv, int nobj) 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); + err = t->ei_encode_fp(NULL, &size2, &objv[oix]); if (err != 0) { if (err != -1) { fail("size calculation returned non zero but not -1"); @@ -272,7 +304,7 @@ void decode_encode(struct Type** tv, int nobj) } MESSAGE("ei_encode_%s, arg is type %s", t->name, t->type); size3 = 0; - err = t->ei_encode_fp(outp, &size3, &obj); + err = t->ei_encode_fp(outp, &size3, &objv[oix]); if (err != 0) { if (err != -1) { fail("returned non zero but not -1"); @@ -288,7 +320,7 @@ void decode_encode(struct Type** tv, int nobj) } MESSAGE("ei_x_encode_%s, arg is type %s", t->name, t->type); - err = t->ei_x_encode_fp(&arg, &obj); + err = t->ei_x_encode_fp(&arg, &objv[oix]); if (err != 0) { if (err != -1) { fail("returned non zero but not -1"); @@ -306,6 +338,37 @@ void decode_encode(struct Type** tv, int nobj) 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 (oix > 0) { + fail("Container not complete"); } send_buffer(out_buf, outp - out_buf); send_buffer(arg.buff, arg.index); -- cgit v1.2.3 From c543d5bff7fb23c3f44cc4817c0654117de78919 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 12 Mar 2014 20:11:10 +0100 Subject: erts: Change external format for maps to be: 116,Arity, K1,V1,K2,V2,...,Kn,Vn instead of: 116,Arity, K1,K2,...,Kn, V1,V2,....,Vn We think this will be better for future internal map structures like HAMT. Would be bad if we need to iterate twice over HAMT in term_to_binary, one for keys and one for values. --- lib/debugger/test/map_SUITE.erl | 9 +++++---- lib/erl_interface/doc/src/ei.xml | 18 ++++++++---------- .../ei_decode_encode_test.c | 5 +++-- .../java_src/com/ericsson/otp/erlang/OtpErlangMap.java | 4 ---- lib/jinterface/test/jinterface_SUITE_data/Maps.java | 8 ++++---- 5 files changed, 20 insertions(+), 24 deletions(-) (limited to 'lib') 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 1756ee8a7d..90495eebd6 100644 --- a/lib/erl_interface/doc/src/ei.xml +++ b/lib/erl_interface/doc/src/ei.xml @@ -422,19 +422,18 @@ ei_x_encode_empty_list(&x); Encode a map

This function encodes a map header, with a specified arity. The next - arity terms encoded will be the keys of the map, and the next - arity terms after that will be the corresponding values in - same order.

+ arity*2 terms encoded will be the keys and values of the map + encoded in the following order: K1, V1, K2, V2, ..., Kn, Vn. +

E.g. to encode the map #{a => "Apple", b => "Banana"}:

 ei_x_encode_map_header(&x, 2);
 ei_x_encode_atom(&x, "a");
-ei_x_encode_atom(&x, "b");
 ei_x_encode_string(&x, "Apple");
+ei_x_encode_atom(&x, "b");
 ei_x_encode_string(&x, "Banana");
         
-

A correctly encoded map can not have duplicate keys, but no check - for duplicate keys is done by this function.

+

A correctly encoded map can not have duplicate keys.

@@ -664,10 +663,9 @@ ei_x_encode_string(&x, "Banana");

This function decodes a map header from the binary format. The number of key-value pairs is returned in - arity. Keys and values follows, first all keys and then all values, - which makes a total of arity*2 terms. - Keys and values are paired according to their order, the first key - with the first value and so on. If arity is zero, it's an empty map. + *arity. Keys and values follow in the following order: + K1, V1, K2, V2, ..., Kn, Vn. This makes a total of + arity*2 terms. If arity is zero, it's an empty map. A correctly encoded map does not have duplicate keys.

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 790d498a1d..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 @@ -527,8 +527,9 @@ TESTCASE(test_ei_decode_encode) { /* #{atom => atom, atom => pid, port => ref }*/ struct Type* map[] = { &map_type, - &my_atom_type, &my_atom_type, &port_type, - &my_atom_type, &pid_type, &ref_type + &my_atom_type, &my_atom_type, + &my_atom_type, &pid_type, + &port_type, &ref_type }; decode_encode(map, 7); } 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); -- cgit v1.2.3 From a996e168bfebe599cfe393cd132a87984d905d84 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 13 Mar 2014 15:23:44 +0100 Subject: erts: Add distribution capability flag for maps DFLAG_MAP_TAG This is just a preparation to allow detection of older nodes that do not understand maps (R16 and older). --- lib/erl_interface/src/connect/ei_connect.c | 5 +++-- lib/erl_interface/src/connect/ei_connect_int.h | 3 ++- lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractNode.java | 5 +++-- lib/kernel/include/dist.hrl | 3 ++- lib/kernel/src/dist_util.erl | 5 +++-- 5 files changed, 13 insertions(+), 8 deletions(-) (limited to 'lib') 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/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/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), -- cgit v1.2.3