diff options
author | Björn Gustavsson <[email protected]> | 2019-06-03 11:28:59 +0200 |
---|---|---|
committer | GitHub <[email protected]> | 2019-06-03 11:28:59 +0200 |
commit | fbee646c4ff63327512f25eb07be0ede66e55599 (patch) | |
tree | 2e077ed99baf611adf6d52c6a6b1d0aab26356ce | |
parent | 6e3ce6cac718ff0eae1349eb0b4ab8513abba343 (diff) | |
parent | 5fef9df3faf0504c5c281a5720b992c19c94a6c2 (diff) | |
download | otp-fbee646c4ff63327512f25eb07be0ede66e55599.tar.gz otp-fbee646c4ff63327512f25eb07be0ede66e55599.tar.bz2 otp-fbee646c4ff63327512f25eb07be0ede66e55599.zip |
Merge pull request #2246 from bjorng/bjorn/erl_interface/term-printing/OTP-15814
Support printing of maps and funs in ei_print_term()
-rw-r--r-- | lib/erl_interface/src/decode/decode_fun.c | 13 | ||||
-rw-r--r-- | lib/erl_interface/src/decode/decode_skip.c | 1 | ||||
-rw-r--r-- | lib/erl_interface/src/misc/ei_printterm.c | 37 | ||||
-rw-r--r-- | lib/erl_interface/test/ei_decode_encode_SUITE.erl | 8 | ||||
-rw-r--r-- | lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c | 1 | ||||
-rw-r--r-- | lib/erl_interface/test/ei_print_SUITE.erl | 27 | ||||
-rw-r--r-- | lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c | 141 |
7 files changed, 198 insertions, 30 deletions
diff --git a/lib/erl_interface/src/decode/decode_fun.c b/lib/erl_interface/src/decode/decode_fun.c index 3a7a2b01c1..db71007505 100644 --- a/lib/erl_interface/src/decode/decode_fun.c +++ b/lib/erl_interface/src/decode/decode_fun.c @@ -77,10 +77,12 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p) } if (p != NULL) { p->u.closure.n_free_vars = n; - p->u.closure.free_var_len = ix - ix0; - p->u.closure.free_vars = ei_malloc(ix - ix0); - if (!(p->u.closure.free_vars)) return -1; - memcpy(p->u.closure.free_vars, s + ix0, ix - ix0); + p->u.closure.free_var_len = ix - ix0; + if (p->u.closure.free_var_len > 0) { + p->u.closure.free_vars = ei_malloc(p->u.closure.free_var_len); + if (!(p->u.closure.free_vars)) return -1; + memcpy(p->u.closure.free_vars, s + ix0, p->u.closure.free_var_len); + } } s += ix; *index += s-s0; @@ -146,6 +148,7 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p) else { p_arity = NULL; } + ix = 0; if (ei_decode_atom_as(s, &ix, p_module, MAXATOMLEN_UTF8, ERLANG_UTF8, NULL, NULL) < 0) return -1; @@ -171,6 +174,8 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p) } if (ei_decode_long(s, &ix, p_arity) < 0) return -1; + s += ix; + *index += s - s0; return 0; } default: diff --git a/lib/erl_interface/src/decode/decode_skip.c b/lib/erl_interface/src/decode/decode_skip.c index 736c00e074..0622ce7d59 100644 --- a/lib/erl_interface/src/decode/decode_skip.c +++ b/lib/erl_interface/src/decode/decode_skip.c @@ -97,6 +97,7 @@ int ei_skip_term(const char* buf, int* index) break; case ERL_FUN_EXT: case ERL_NEW_FUN_EXT: + case ERL_EXPORT_EXT: if (ei_decode_fun(buf, index, NULL) < 0) return -1; break; default: diff --git a/lib/erl_interface/src/misc/ei_printterm.c b/lib/erl_interface/src/misc/ei_printterm.c index 5c40fb7747..a94d6e2ad8 100644 --- a/lib/erl_interface/src/misc/ei_printterm.c +++ b/lib/erl_interface/src/misc/ei_printterm.c @@ -121,6 +121,7 @@ static int print_term(FILE* fp, ei_x_buff* x, erlang_pid pid; erlang_port port; erlang_ref ref; + erlang_fun fun; double d; long l; @@ -306,12 +307,46 @@ static int print_term(FILE* fp, ei_x_buff* x, } break; - case ERL_FLOAT_EXT: case NEW_FLOAT_EXT: if (ei_decode_double(buf, index, &d) < 0) goto err; ch_written += xprintf(fp, x, "%f", d); break; + case ERL_MAP_EXT: + if (ei_decode_map_header(buf, &tindex, &n) < 0) goto err; + ch_written += xprintf(fp, x, "#{"); + for (i = 0; i < n; ++i) { + r = print_term(fp, x, buf, &tindex); + if (r < 0) goto err; + ch_written += r; + ch_written += xprintf(fp, x, " => "); + r = print_term(fp, x, buf, &tindex); + if (r < 0) goto err; + ch_written += r; + if (i < n-1) { + xputs(", ", fp, x); ch_written += 2; + } + } + *index = tindex; + xputc('}', fp, x); ch_written++; + break; + case ERL_FUN_EXT: + case ERL_NEW_FUN_EXT: + case ERL_EXPORT_EXT: + if (ei_decode_fun(buf, &tindex, &fun) < 0) goto err; + if (fun.type == EI_FUN_EXPORT) { + ch_written += xprintf(fp, x, "fun %s:%s/%ld", + fun.module, + fun.u.exprt.func, + fun.arity); + } else { + ch_written += xprintf(fp, x, "#Fun{%s.%ld.%lu}", + fun.module, + fun.u.closure.index, + fun.u.closure.uniq); + } + *index = tindex; + break; default: goto err; } diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE.erl b/lib/erl_interface/test/ei_decode_encode_SUITE.erl index 3451d9f503..0204b4cfd6 100644 --- a/lib/erl_interface/test/ei_decode_encode_SUITE.erl +++ b/lib/erl_interface/test/ei_decode_encode_SUITE.erl @@ -48,7 +48,8 @@ init_per_testcase(Case, Config) -> test_ei_decode_encode(Config) when is_list(Config) -> P = runner:start(Config, ?test_ei_decode_encode), - Fun = fun (X) -> {X,true} end, + Fun1 = fun (X) -> {X,true} end, + Fun2 = fun runner:init_per_testcase/3, Pid = self(), Port = case os:type() of {win32,_} -> @@ -70,7 +71,8 @@ test_ei_decode_encode(Config) when is_list(Config) -> BigLargeB = 1 bsl 11112 + BigSmallB, BigLargeC = BigSmallA * BigSmallB * BigSmallC * BigSmallA, - send_rec(P, Fun), + send_rec(P, Fun1), + send_rec(P, Fun2), send_rec(P, Pid), send_rec(P, Port), send_rec(P, Ref), @@ -115,7 +117,7 @@ test_ei_decode_encode(Config) when is_list(Config) -> 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, [atom | Fun1]), send_rec(P, #{}), send_rec(P, #{key => value}), send_rec(P, maps:put(Port, Ref, #{key => value, key2 => Pid})), 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 85ca6c56e9..512f9ed0c7 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 @@ -564,6 +564,7 @@ TESTCASE(test_ei_decode_encode) ei_init(); decode_encode_one(&fun_type); + decode_encode_one(&fun_type); decode_encode_one(&pid_type); decode_encode_one(&port_type); decode_encode_one(&ref_type); diff --git a/lib/erl_interface/test/ei_print_SUITE.erl b/lib/erl_interface/test/ei_print_SUITE.erl index c75ce55a7d..f2a2548183 100644 --- a/lib/erl_interface/test/ei_print_SUITE.erl +++ b/lib/erl_interface/test/ei_print_SUITE.erl @@ -26,7 +26,8 @@ -export([all/0, suite/0, init_per_testcase/2, - atoms/1, tuples/1, lists/1, strings/1]). + atoms/1, tuples/1, lists/1, strings/1, + maps/1, funs/1]). -import(runner, [get_term/1]). @@ -36,8 +37,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. -all() -> - [atoms, tuples, lists, strings]. +all() -> + [atoms, tuples, lists, strings, maps, funs]. init_per_testcase(Case, Config) -> runner:init_per_testcase(?MODULE, Case, Config). @@ -142,3 +143,23 @@ strings(Config) when is_list(Config) -> runner:recv_eot(P), ok. + +maps(Config) -> + P = runner:start(Config, ?maps), + + {term, "#{}"} = get_term(P), + {term, "#{key => value}"} = get_term(P), + {term, "#{key => value, another_key => {ok, 42}}"} = get_term(P), + + runner:recv_eot(P), + ok. + +funs(Config) -> + P = runner:start(Config, ?funs), + + {term, "#Fun{some_module.42.3735928559}"} = get_term(P), + {term, "#Fun{some_module.37.195935983}"} = get_term(P), + {term, "fun erlang:abs/1"} = get_term(P), + + runner:recv_eot(P), + ok. diff --git a/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c b/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c index 80be3016e6..0e2b24e45a 100644 --- a/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c +++ b/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c @@ -29,6 +29,46 @@ */ static void +send_printed_buf(ei_x_buff* x) +{ + char* b = NULL; + char fn[256]; + char *tmp = getenv("temp"); + FILE* f; + int n, index = 0, ver; + +#ifdef VXWORKS + tmp = "."; +#else + if (tmp == NULL) { + tmp = "/tmp"; + } +#endif + strcpy(fn, tmp); + strcat(fn, "/ei_print_test.txt"); + f = fopen(fn, "w+"); + ei_decode_version(x->buff, &index, &ver); + n = ei_print_term(f, x->buff, &index); + if (n < 0) { + fclose(f); + x->index = 0; + ei_x_format(x, "~s", "ERROR: term decoding failed"); + send_bin_term(x); + } else { + fseek(f, 0, SEEK_SET); + b = malloc(n+1); + fread(b, 1, n, f); + b[n] = '\0'; + fclose(f); + x->index = 0; + ei_x_format(x, "~s", b); + send_bin_term(x); + free(b); + } +} + + +static void send_printed3(char* format, char* p1, char* p2, int fl) { char* b = NULL; @@ -43,25 +83,7 @@ send_printed3(char* format, char* p1, char* p2, int fl) } else { ei_x_format(&x, format, p1, p2); } -#ifdef VXWORKS - tmp = "."; -#else - if (tmp == NULL) tmp = "/tmp"; -#endif - strcpy(fn, tmp); - strcat(fn, "/ei_print_test.txt"); - f = fopen(fn, "w+"); - ei_decode_version(x.buff, &index, &ver); - n = ei_print_term(f, x.buff, &index); - fseek(f, 0, SEEK_SET); - b = malloc(n+1); - fread(b, 1, n, f); - b[n] = '\0'; - fclose(f); - x.index = 0; - ei_x_format(&x, "~s", b); - send_bin_term(&x); - free(b); + send_printed_buf(&x); ei_x_free(&x); } @@ -184,4 +206,85 @@ TESTCASE(strings) report(1); } +TESTCASE(maps) +{ + ei_x_buff x; + + ei_init(); + + ei_x_new_with_version(&x); + ei_x_encode_map_header(&x, 0); + send_printed_buf(&x); + ei_x_free(&x); + + ei_x_new_with_version(&x); + ei_x_encode_map_header(&x, 1); + ei_x_encode_atom(&x, "key"); + ei_x_encode_atom(&x, "value"); + send_printed_buf(&x); + ei_x_free(&x); + + ei_x_new_with_version(&x); + ei_x_encode_map_header(&x, 2); + ei_x_encode_atom(&x, "key"); + ei_x_encode_atom(&x, "value"); + ei_x_encode_atom(&x, "another_key"); + ei_x_encode_tuple_header(&x, 2); + ei_x_encode_atom(&x, "ok"); + ei_x_encode_long(&x, 42L); + send_printed_buf(&x); + ei_x_free(&x); + + report(1); +} + +TESTCASE(funs) +{ + ei_x_buff x; + erlang_pid self; + erlang_fun fun; + + strcpy(self.node, "node@host"); + self.num = 9; + self.serial = 99; + self.creation = 1; + + ei_init(); + + ei_x_new_with_version(&x); + fun.arity = -1; /* Will encode as FUN_EXT */ + strcpy(fun.module, "some_module"); + fun.type = EI_FUN_CLOSURE; + fun.u.closure.pid = self; + fun.u.closure.index = fun.u.closure.old_index = 42; + fun.u.closure.uniq = 0xDEADBEEF; + fun.u.closure.n_free_vars = 0; + fun.u.closure.free_var_len = 0; + ei_x_encode_fun(&x, &fun); + send_printed_buf(&x); + ei_x_free(&x); + ei_x_new_with_version(&x); + fun.arity = 0; /* Will encode as NEW_FUN_EXT */ + strcpy(fun.module, "some_module"); + fun.type = EI_FUN_CLOSURE; + fun.u.closure.pid = self; + fun.u.closure.index = fun.u.closure.old_index = 37; + fun.u.closure.uniq = 0xBADBEEF; + fun.u.closure.n_free_vars = 0; + fun.u.closure.free_var_len = 0; + ei_x_encode_fun(&x, &fun); + send_printed_buf(&x); + ei_x_free(&x); + + ei_x_new_with_version(&x); + fun.arity = 1; + strcpy(fun.module, "erlang"); + fun.type = EI_FUN_EXPORT; + fun.u.exprt.func = "abs"; + ei_x_encode_fun(&x, &fun); + send_printed_buf(&x); + ei_x_free(&x); + + report(1); +} |