From 08d67b91c5daf5eb5e8d974ca08bb1b634c4ae2a Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Fri, 7 May 2010 18:05:56 +0200 Subject: erl_nif: add enif_is_list and enif_is_tuple Add new NIF API functions - enif_is_list - enif_is_tuple Signed-off-by: Tuncer Ayaz --- erts/doc/src/erl_nif.xml | 8 +++++++ erts/emulator/beam/erl_nif.c | 10 ++++++++ erts/emulator/beam/erl_nif_api_funcs.h | 4 ++++ erts/emulator/test/nif_SUITE.erl | 12 +++++++--- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 33 ++++++++++++++++++++++++++- 5 files changed, 63 insertions(+), 4 deletions(-) (limited to 'erts') diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml index 5ec844e2ad..dda6354c61 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -597,6 +597,14 @@ typedef enum { Determine if a term is a reference

Return true if term is a reference.

+ intenif_is_tuple(ErlNifEnv* env, ERL_NIF_TERM term) + Determine if a term is a tuple +

Return true if term is a tuple.

+
+ intenif_is_list(ErlNifEnv* env, ERL_NIF_TERM term) + Determine if a term is a list +

Return true if term is a list.

+
ERL_NIF_TERMenif_make_atom(ErlNifEnv* env, const char* name) Create an atom term

Create an atom term from the C-string name. Unlike other terms, atom diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index cee4df72a2..a07aa2e81f 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -248,6 +248,16 @@ int enif_is_ref(ErlNifEnv* env, ERL_NIF_TERM term) return is_ref(term); } +int enif_is_tuple(ErlNifEnv* env, ERL_NIF_TERM term) +{ + return is_tuple(term); +} + +int enif_is_list(ErlNifEnv* env, ERL_NIF_TERM term) +{ + return is_list(term) || is_nil(term); +} + static void aligned_binary_dtor(struct enif_tmp_obj_t* obj) { erts_free_aligned_binary_bytes_extra((byte*)obj,ERTS_ALC_T_TMP); diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h index fe8d2664e1..1ef27c3df3 100644 --- a/erts/emulator/beam/erl_nif_api_funcs.h +++ b/erts/emulator/beam/erl_nif_api_funcs.h @@ -106,6 +106,8 @@ ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_resource,(ErlNifEnv*, void* obj)); ERL_NIF_API_FUNC_DECL(int,enif_get_resource,(ErlNifEnv*, ERL_NIF_TERM term, ErlNifResourceType* type, void** objp)); ERL_NIF_API_FUNC_DECL(unsigned,enif_sizeof_resource,(ErlNifEnv*, void* obj)); ERL_NIF_API_FUNC_DECL(unsigned char*,enif_make_new_binary,(ErlNifEnv*,unsigned size,ERL_NIF_TERM* termp)); +ERL_NIF_API_FUNC_DECL(int,enif_is_list,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(int,enif_is_tuple,(ErlNifEnv*, ERL_NIF_TERM term)); /* ** Add last to keep compatibility on Windows!!! @@ -198,6 +200,8 @@ ERL_NIF_API_FUNC_DECL(unsigned char*,enif_make_new_binary,(ErlNifEnv*,unsigned s # define enif_get_resource ERL_NIF_API_FUNC_MACRO(enif_get_resource) # define enif_sizeof_resource ERL_NIF_API_FUNC_MACRO(enif_sizeof_resource) # define enif_make_new_binary ERL_NIF_API_FUNC_MACRO(enif_make_new_binary) +# define enif_is_list ERL_NIF_API_FUNC_MACRO(enif_is_list) +# define enif_is_tuple ERL_NIF_API_FUNC_MACRO(enif_is_tuple) #endif #ifndef enif_make_list1 diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 522caec8f1..36bcfe26cc 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -28,7 +28,7 @@ -export([all/1, fin_per_testcase/2, basic/1, reload/1, upgrade/1, heap_frag/1, types/1, many_args/1, binaries/1, get_string/1, get_atom/1, api_macros/1, from_array/1, iolist_as_binary/1, resource/1, resource_takeover/1, - threading/1, neg/1]). + threading/1, neg/1, is_checks/1]). -export([many_args_100/100]). -define(nif_stub,nif_stub_error(?LINE)). @@ -36,7 +36,7 @@ all(suite) -> [basic, reload, upgrade, heap_frag, types, many_args, binaries, get_string, get_atom, api_macros, from_array, iolist_as_binary, resource, - resource_takeover, threading, neg]. + resource_takeover, threading, neg, is_checks]. %%init_per_testcase(_Case, Config) -> %% ?line Dog = ?t:timetrap(?t:seconds(60*60*24)), @@ -759,7 +759,12 @@ neg(Config) when is_list(Config) -> ?line verify_tmpmem(TmpMem), ?line ok. - +is_checks(doc) -> ["Test all enif_is functions"]; +is_checks(Config) when is_list(Config) -> + ?line ensure_lib_loaded(Config, 1), + ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end, + self(), hd(erlang:ports()), [], [1,9,9,8], + {hejsan, "hejsan", [$h,"ejs",<<"an">>]}). ensure_lib_loaded(Config) -> ensure_lib_loaded(Config, 1). @@ -855,6 +860,7 @@ get_resource(_,_) -> ?nif_stub. release_resource(_) -> ?nif_stub. last_resource_dtor_call() -> ?nif_stub. make_new_resource(_,_) -> ?nif_stub. +check_is(_,_,_,_,_,_,_,_,_,_) -> ?nif_stub. nif_stub_error(Line) -> exit({nif_not_loaded,module,?MODULE,line,Line}). diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 3ad4f93374..22d0d5a93b 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -630,6 +630,36 @@ static ERL_NIF_TERM release_resource(ErlNifEnv* env, int argc, const ERL_NIF_TER return enif_make_atom(env,"ok"); } +/* + * argv[0] an atom + * argv[1] a binary + * argv[2] a ref + * argv[3] 'ok' + * argv[4] a fun + * argv[5] a pid + * argv[6] a port + * argv[7] an empty list + * argv[8] a non-empty list + * argv[9] a tuple + */ +static ERL_NIF_TERM check_is(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + ERL_NIF_TERM ok_atom = enif_make_atom(env, "ok"); + + if (!enif_is_atom(env, argv[0])) return enif_make_badarg(env); + if (!enif_is_binary(env, argv[1])) return enif_make_badarg(env); + if (!enif_is_ref(env, argv[2])) return enif_make_badarg(env); + if (!enif_is_identical(env, argv[3], ok_atom)) return enif_make_badarg(env); + if (!enif_is_fun(env, argv[4])) return enif_make_badarg(env); + if (!enif_is_pid(env, argv[5])) return enif_make_badarg(env); + if (!enif_is_port(env, argv[6])) return enif_make_badarg(env); + if (!enif_is_empty_list(env, argv[7])) return enif_make_badarg(env); + if (!enif_is_list(env, argv[7])) return enif_make_badarg(env); + if (!enif_is_list(env, argv[8])) return enif_make_badarg(env); + if (!enif_is_tuple(env, argv[9])) return enif_make_badarg(env); + + return ok_atom; +} static ErlNifFunc nif_funcs[] = { @@ -656,7 +686,8 @@ static ErlNifFunc nif_funcs[] = {"get_resource", 2, get_resource}, {"release_resource", 1, release_resource}, {"last_resource_dtor_call", 0, last_resource_dtor_call}, - {"make_new_resource", 2, make_new_resource} + {"make_new_resource", 2, make_new_resource}, + {"check_is", 10, check_is} }; -- cgit v1.2.3 From 8c8663f32f0e9fc2b9483e2b99cee5f703640e88 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Fri, 7 May 2010 18:12:05 +0200 Subject: erl_nif: add enif_get_atom_length and enif_get_list_length Add new NIF API functions - enif_get_atom_length - enif_get_list_length Signed-off-by: Tuncer Ayaz --- erts/doc/src/erl_nif.xml | 11 +++++++++ erts/emulator/beam/erl_nif.c | 16 ++++++++++++++ erts/emulator/beam/erl_nif_api_funcs.h | 4 ++++ erts/emulator/test/nif_SUITE.erl | 10 +++++++-- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 32 ++++++++++++++++++++++++++- 5 files changed, 70 insertions(+), 3 deletions(-) (limited to 'erts') diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml index dda6354c61..dc68eb5e5e 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -477,6 +477,12 @@ typedef enum { term is not an atom with maximum length of size-1.

+ intenif_get_atom_length(ErlNifEnv* env, ERL_NIF_TERM term, unsigned* len) + Get the length of atom term. +

Set *len to the length (number of bytes excluding + terminating null character) of term or return false if + term is not an atom.

+
intenif_get_double(ErlNifEnv* env, ERL_NIF_TERM term, double* dp) Read a floating-point number term.

Set *dp to the floating point value of @@ -494,6 +500,11 @@ typedef enum { list or return false if list is not a non-empty list.

+ intenif_get_list_length(ErlNifEnv* env, ERL_NIF_TERM term, unsigned* len) + Get the length of list term. +

Set *len to the length of term or return + false if term is not a list.

+
intenif_get_long(ErlNifEnv* env, ERL_NIF_TERM term, long int* ip) Read an long integer term.

Set *ip to the long integer value of diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index a07aa2e81f..4a3b0ad8ca 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -601,6 +601,15 @@ int enif_get_double(ErlNifEnv* env, Eterm term, double* dp) return 1; } +int enif_get_atom_length(ErlNifEnv* env, Eterm atom, unsigned* len) +{ + Atom* ap; + if (is_not_atom(atom)) return 0; + ap = atom_tab(atom_val(atom)); + *len = ap->len; + return 1; +} + int enif_get_list_cell(ErlNifEnv* env, Eterm term, Eterm* head, Eterm* tail) { Eterm* val; @@ -611,6 +620,13 @@ int enif_get_list_cell(ErlNifEnv* env, Eterm term, Eterm* head, Eterm* tail) return 1; } +int enif_get_list_length(ErlNifEnv* env, Eterm term, unsigned* len) +{ + if (is_not_list(term) && is_not_nil(term)) return 0; + *len = list_length(term); + return 1; +} + ERL_NIF_TERM enif_make_int(ErlNifEnv* env, int i) { #if SIZEOF_INT == ERTS_SIZEOF_ETERM diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h index 1ef27c3df3..4d025567ad 100644 --- a/erts/emulator/beam/erl_nif_api_funcs.h +++ b/erts/emulator/beam/erl_nif_api_funcs.h @@ -108,6 +108,8 @@ ERL_NIF_API_FUNC_DECL(unsigned,enif_sizeof_resource,(ErlNifEnv*, void* obj)); ERL_NIF_API_FUNC_DECL(unsigned char*,enif_make_new_binary,(ErlNifEnv*,unsigned size,ERL_NIF_TERM* termp)); ERL_NIF_API_FUNC_DECL(int,enif_is_list,(ErlNifEnv*, ERL_NIF_TERM term)); ERL_NIF_API_FUNC_DECL(int,enif_is_tuple,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(int,enif_get_atom_length,(ErlNifEnv*, ERL_NIF_TERM atom, unsigned* len)); +ERL_NIF_API_FUNC_DECL(int,enif_get_list_length,(ErlNifEnv* env, ERL_NIF_TERM term, unsigned* len)); /* ** Add last to keep compatibility on Windows!!! @@ -202,6 +204,8 @@ ERL_NIF_API_FUNC_DECL(int,enif_is_tuple,(ErlNifEnv*, ERL_NIF_TERM term)); # define enif_make_new_binary ERL_NIF_API_FUNC_MACRO(enif_make_new_binary) # define enif_is_list ERL_NIF_API_FUNC_MACRO(enif_is_list) # define enif_is_tuple ERL_NIF_API_FUNC_MACRO(enif_is_tuple) +# define enif_get_atom_length ERL_NIF_API_FUNC_MACRO(enif_get_atom_length) +# define enif_get_list_length ERL_NIF_API_FUNC_MACRO(enif_get_list_length) #endif #ifndef enif_make_list1 diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 36bcfe26cc..c2949e7bfa 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -28,7 +28,7 @@ -export([all/1, fin_per_testcase/2, basic/1, reload/1, upgrade/1, heap_frag/1, types/1, many_args/1, binaries/1, get_string/1, get_atom/1, api_macros/1, from_array/1, iolist_as_binary/1, resource/1, resource_takeover/1, - threading/1, neg/1, is_checks/1]). + threading/1, neg/1, is_checks/1, get_length/1]). -export([many_args_100/100]). -define(nif_stub,nif_stub_error(?LINE)). @@ -36,7 +36,7 @@ all(suite) -> [basic, reload, upgrade, heap_frag, types, many_args, binaries, get_string, get_atom, api_macros, from_array, iolist_as_binary, resource, - resource_takeover, threading, neg, is_checks]. + resource_takeover, threading, neg, is_checks, get_length]. %%init_per_testcase(_Case, Config) -> %% ?line Dog = ?t:timetrap(?t:seconds(60*60*24)), @@ -766,6 +766,11 @@ is_checks(Config) when is_list(Config) -> self(), hd(erlang:ports()), [], [1,9,9,8], {hejsan, "hejsan", [$h,"ejs",<<"an">>]}). +get_length(doc) -> ["Test all enif_get_length functions"]; +get_length(Config) when is_list(Config) -> + ?line ensure_lib_loaded(Config, 1), + ?line ok = length_test(hejsan, "hejsan", [], [], not_a_list). + ensure_lib_loaded(Config) -> ensure_lib_loaded(Config, 1). ensure_lib_loaded(Config, Ver) -> @@ -861,6 +866,7 @@ release_resource(_) -> ?nif_stub. last_resource_dtor_call() -> ?nif_stub. make_new_resource(_,_) -> ?nif_stub. check_is(_,_,_,_,_,_,_,_,_,_) -> ?nif_stub. +length_test(_,_,_,_,_) -> ?nif_stub. nif_stub_error(Line) -> exit({nif_not_loaded,module,?MODULE,line,Line}). diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 22d0d5a93b..4d010c58a5 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -661,6 +661,35 @@ static ERL_NIF_TERM check_is(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] return ok_atom; } +/* + * argv[0] atom with length of 6 + * argv[1] list with length of 6 + * argv[2] empty list + * argv[3] not an atom + * argv[4] not a list + */ +static ERL_NIF_TERM length_test(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + unsigned len; + + if (!enif_get_atom_length(env, argv[0], &len) || len != 6) + return enif_make_badarg(env); + + if (!enif_get_list_length(env, argv[1], &len) || len != 6) + return enif_make_badarg(env); + + if (!enif_get_list_length(env, argv[2], &len) || len != 0) + return enif_make_badarg(env); + + if (enif_get_atom_length(env, argv[3], &len)) + return enif_make_badarg(env); + + if (enif_get_list_length(env, argv[4], &len)) + return enif_make_badarg(env); + + return enif_make_atom(env, "ok"); +} + static ErlNifFunc nif_funcs[] = { {"lib_version", 0, lib_version}, @@ -687,7 +716,8 @@ static ErlNifFunc nif_funcs[] = {"release_resource", 1, release_resource}, {"last_resource_dtor_call", 0, last_resource_dtor_call}, {"make_new_resource", 2, make_new_resource}, - {"check_is", 10, check_is} + {"check_is", 10, check_is}, + {"length_test", 5, length_test} }; -- cgit v1.2.3 From dc47b560f0d0ba67fffd083eb79be8797f970012 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Fri, 7 May 2010 18:18:26 +0200 Subject: erl_nif: add make_atom_len, make_existing_atom_len and make_string_len Add new NIF API functions - enif_make_atom_len - enif_make_existing_atom_len - enif_make_string_len These are basically the same as enif_make_atom, enif_make_existing_atom and enif_make_string except that the new functions require a length parameter instead of a null-terminated C-string. Signed-off-by: Tuncer Ayaz --- erts/doc/src/erl_nif.xml | 25 +++++++++++++-- erts/emulator/beam/erl_nif.c | 28 +++++++++++++---- erts/emulator/beam/erl_nif_api_funcs.h | 6 ++++ erts/emulator/test/nif_SUITE.erl | 23 ++++++++++++-- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 45 ++++++++++++++++++++++++++- 5 files changed, 115 insertions(+), 12 deletions(-) (limited to 'erts') diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml index dc68eb5e5e..03bd42d3b1 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -618,8 +618,14 @@ typedef enum { ERL_NIF_TERMenif_make_atom(ErlNifEnv* env, const char* name) Create an atom term -

Create an atom term from the C-string name. Unlike other terms, atom - terms may be saved and used between NIF calls.

+

Create an atom term from the null-terminated C-string name. + Unlike other terms, atom terms may be saved and used between NIF calls.

+
+ ERL_NIF_TERMenif_make_atom_len(ErlNifEnv* env, const char* name, size_t len) + Create an atom term +

Create an atom term from the string name with length len. + Null-characters are treated as any other characters. + Unlike other terms, atom terms may be saved and used between NIF calls.

ERL_NIF_TERMenif_make_badarg(ErlNifEnv* env) Make a badarg exception. @@ -639,10 +645,17 @@ typedef enum { intenif_make_existing_atom(ErlNifEnv* env, const char* name, ERL_NIF_TERM* atom) Create an existing atom term

Try to create the term of an already existing atom from - the C-string name. If the atom already exist store the + the null-terminated C-string name. If the atom already exists store the term in *atom and return true, otherwise return false.

+ intenif_make_existing_atom_len(ErlNifEnv* env, const char* name, size_t len, ERL_NIF_TERM* atom) + Create an existing atom term +

Try to create the term of an already existing atom from the + string name with length len. Null-characters are treated + as any other characters. If the atom already exists store the term + in *atom and return true, otherwise return false.

+
ERL_NIF_TERMenif_make_int(ErlNifEnv* env, int i) Create an integer term

Create an integer term.

@@ -711,6 +724,12 @@ typedef enum {

Create a list containing the characters of the null-terminated string string with encoding encoding.

+ ERL_NIF_TERMenif_make_string_len(ErlNifEnv* env, const char* string, size_t len, ErlNifCharEncoding encoding) + Create a string. +

Create a list containing the characters of the string string with + length len and encoding encoding. + Null-characters are treated as any other characters.

+
ERL_NIF_TERMenif_make_sub_binary(ErlNifEnv* env, ERL_NIF_TERM bin_term, unsigned pos, unsigned size) Make a subbinary term. diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 4a3b0ad8ca..7095ae03e7 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -666,12 +666,23 @@ ERL_NIF_TERM enif_make_double(ErlNifEnv* env, double d) ERL_NIF_TERM enif_make_atom(ErlNifEnv* env, const char* name) { - return am_atom_put(name, sys_strlen(name)); + return enif_make_atom_len(env, name, sys_strlen(name)); +} + +ERL_NIF_TERM enif_make_atom_len(ErlNifEnv* env, const char* name, size_t len) +{ + return am_atom_put(name, len); } int enif_make_existing_atom(ErlNifEnv* env, const char* name, ERL_NIF_TERM* atom) { - return erts_atom_get(name, sys_strlen(name), atom); + return enif_make_existing_atom_len(env, name, sys_strlen(name), atom); +} + +int enif_make_existing_atom_len(ErlNifEnv* env, const char* name, size_t len, + ERL_NIF_TERM* atom) +{ + return erts_atom_get(name, len, atom); } ERL_NIF_TERM enif_make_tuple(ErlNifEnv* env, unsigned cnt, ...) @@ -750,11 +761,16 @@ ERL_NIF_TERM enif_make_list_from_array(ErlNifEnv* env, const ERL_NIF_TERM arr[], ERL_NIF_TERM enif_make_string(ErlNifEnv* env, const char* string, ErlNifCharEncoding encoding) -{ - Sint n = sys_strlen(string); - Eterm* hp = alloc_heap(env,n*2); +{ + return enif_make_string_len(env, string, sys_strlen(string), encoding); +} + +ERL_NIF_TERM enif_make_string_len(ErlNifEnv* env, const char* string, + size_t len, ErlNifCharEncoding encoding) +{ + Eterm* hp = alloc_heap(env,len*2); ASSERT(encoding == ERL_NIF_LATIN1); - return erts_bld_string_n(&hp,NULL,string,n); + return erts_bld_string_n(&hp,NULL,string,len); } ERL_NIF_TERM enif_make_ref(ErlNifEnv* env) diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h index 4d025567ad..44bcca9ca4 100644 --- a/erts/emulator/beam/erl_nif_api_funcs.h +++ b/erts/emulator/beam/erl_nif_api_funcs.h @@ -110,6 +110,9 @@ ERL_NIF_API_FUNC_DECL(int,enif_is_list,(ErlNifEnv*, ERL_NIF_TERM term)); ERL_NIF_API_FUNC_DECL(int,enif_is_tuple,(ErlNifEnv*, ERL_NIF_TERM term)); ERL_NIF_API_FUNC_DECL(int,enif_get_atom_length,(ErlNifEnv*, ERL_NIF_TERM atom, unsigned* len)); ERL_NIF_API_FUNC_DECL(int,enif_get_list_length,(ErlNifEnv* env, ERL_NIF_TERM term, unsigned* len)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM, enif_make_atom_len,(ErlNifEnv* env, const char* name, size_t len)); +ERL_NIF_API_FUNC_DECL(int, enif_make_existing_atom_len,(ErlNifEnv* env, const char* name, size_t len, ERL_NIF_TERM* atom)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_string_len,(ErlNifEnv* env, const char* string, size_t len, ErlNifCharEncoding)); /* ** Add last to keep compatibility on Windows!!! @@ -206,6 +209,9 @@ ERL_NIF_API_FUNC_DECL(int,enif_get_list_length,(ErlNifEnv* env, ERL_NIF_TERM ter # define enif_is_tuple ERL_NIF_API_FUNC_MACRO(enif_is_tuple) # define enif_get_atom_length ERL_NIF_API_FUNC_MACRO(enif_get_atom_length) # define enif_get_list_length ERL_NIF_API_FUNC_MACRO(enif_get_list_length) +# define enif_make_atom_len ERL_NIF_API_FUNC_MACRO(enif_make_atom_len) +# define enif_make_existing_atom_len ERL_NIF_API_FUNC_MACRO(enif_make_existing_atom_len) +# define enif_make_string_len ERL_NIF_API_FUNC_MACRO(enif_make_string_len) #endif #ifndef enif_make_list1 diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index c2949e7bfa..161e38c68a 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -28,7 +28,7 @@ -export([all/1, fin_per_testcase/2, basic/1, reload/1, upgrade/1, heap_frag/1, types/1, many_args/1, binaries/1, get_string/1, get_atom/1, api_macros/1, from_array/1, iolist_as_binary/1, resource/1, resource_takeover/1, - threading/1, neg/1, is_checks/1, get_length/1]). + threading/1, neg/1, is_checks/1, get_length/1, make_atom/1, make_string/1]). -export([many_args_100/100]). -define(nif_stub,nif_stub_error(?LINE)). @@ -36,7 +36,8 @@ all(suite) -> [basic, reload, upgrade, heap_frag, types, many_args, binaries, get_string, get_atom, api_macros, from_array, iolist_as_binary, resource, - resource_takeover, threading, neg, is_checks, get_length]. + resource_takeover, threading, neg, is_checks, get_length, make_atom, + make_string]. %%init_per_testcase(_Case, Config) -> %% ?line Dog = ?t:timetrap(?t:seconds(60*60*24)), @@ -783,6 +784,22 @@ ensure_lib_loaded(Config, Ver) -> ok end. +make_atom(Config) when is_list(Config) -> + ?line ensure_lib_loaded(Config, 1), + An0Atom = an0atom, + An0Atom0 = 'an\000atom\000', + ?line Atoms = make_atoms(), + ?line 7 = size(Atoms), + ?line Atoms = {An0Atom,An0Atom,An0Atom,An0Atom0,An0Atom,An0Atom,An0Atom0}. + +make_string(Config) when is_list(Config) -> + ?line ensure_lib_loaded(Config, 1), + ?line Strings = make_strings(), + ?line 4 = size(Strings), + A0String = "a0string", + A0String0 = [$a,0,$s,$t,$r,$i,$n,$g,0], + ?line Strings = {A0String,A0String,A0String,A0String0}. + tmpmem() -> case erlang:system_info({allocator,temp_alloc}) of false -> undefined; @@ -867,6 +884,8 @@ last_resource_dtor_call() -> ?nif_stub. make_new_resource(_,_) -> ?nif_stub. check_is(_,_,_,_,_,_,_,_,_,_) -> ?nif_stub. length_test(_,_,_,_,_) -> ?nif_stub. +make_atoms() -> ?nif_stub. +make_strings() -> ?nif_stub. nif_stub_error(Line) -> exit({nif_not_loaded,module,?MODULE,line,Line}). diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 4d010c58a5..73226a09cb 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -690,6 +690,47 @@ static ERL_NIF_TERM length_test(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg return enif_make_atom(env, "ok"); } +static ERL_NIF_TERM make_atoms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + ERL_NIF_TERM arr[7]; + ERL_NIF_TERM existingatom0a, existingatom0b; + ERL_NIF_TERM existing0atom0; + const char * const an0atom = "an0atom"; + const char an0atom0[8] = {'a','n','\0','a','t','o','m',0}; + + arr[0] = enif_make_atom(env, "an0atom"); + arr[1] = enif_make_atom_len(env, "an0atom", 7); + arr[2] = enif_make_atom_len(env, an0atom, 7); + arr[3] = enif_make_atom_len(env, an0atom0, 8); + + if (!enif_make_existing_atom(env, "an0atom", &existingatom0a)) + return enif_make_atom(env, "error"); + arr[4] = existingatom0a; + + if (!enif_make_existing_atom_len(env, an0atom, 7, &existingatom0b)) + return enif_make_atom(env, "error"); + arr[5] = existingatom0b; + + if (!enif_make_existing_atom_len(env, an0atom0, 8, &existing0atom0)) + return enif_make_atom(env, "error"); + arr[6] = existing0atom0; + + return enif_make_tuple7(env, + arr[0],arr[1],arr[2],arr[3],arr[4],arr[5],arr[6]); +} + +static ERL_NIF_TERM make_strings(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + const char a0string[8] = {'a','0','s','t','r','i','n','g'}; + const char a0string0[9] = {'a','\0','s','t','r','i','n','g',0}; + + return enif_make_tuple4(env, + enif_make_string(env, "a0string", ERL_NIF_LATIN1), + enif_make_string_len(env, "a0string", 8, ERL_NIF_LATIN1), + enif_make_string_len(env, a0string, 8, ERL_NIF_LATIN1), + enif_make_string_len(env, a0string0, 9, ERL_NIF_LATIN1)); +} + static ErlNifFunc nif_funcs[] = { {"lib_version", 0, lib_version}, @@ -717,7 +758,9 @@ static ErlNifFunc nif_funcs[] = {"last_resource_dtor_call", 0, last_resource_dtor_call}, {"make_new_resource", 2, make_new_resource}, {"check_is", 10, check_is}, - {"length_test", 5, length_test} + {"length_test", 5, length_test}, + {"make_atoms", 0, make_atoms}, + {"make_strings", 0, make_strings} }; -- cgit v1.2.3