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(-) 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