diff --git a/doc/luerl.txt b/doc/luerl.txt index 1504e7e..c515a4f 100644 --- a/doc/luerl.txt +++ b/doc/luerl.txt @@ -161,13 +161,6 @@ Interface functions - New Version luerl:decode_list([LuerlTerm], State) -> [Term] Decode a list of Luerl terms into a list of Erlang representations. - luerl:put_private(Key, Value, State) -> State. - Put a private value into Luerl that is not exposed to the runtime. - - luerl:get_private(Key, State) -> Term. - Get a private value from Luerl. - - AUTHORS Jean Chassoul, Robert Virding. diff --git a/doc/src/luerl.3.md b/doc/src/luerl.3.md index d07ca8f..592c9a8 100644 --- a/doc/src/luerl.3.md +++ b/doc/src/luerl.3.md @@ -113,3 +113,12 @@ Decode a term in the Luerl form into its Erlang representation. #### luerl:decode_list([LuerlTerm], State) -> [Term] Decode a list of Luerl terms into a list of Erlang representations. + +#### luerl:put_private(Key, Term, State) -> State. +Puts a private value under key that is not exposed to the runtime. + +#### luerl:get_private(Key, State) -> Term. +Get a private value for the given key. + +#### luerl:get_private(Key, State) -> Term. +Deletes the private value for the given key. diff --git a/include/luerl.hrl b/include/luerl.hrl index 41cd5f0..824dcac 100644 --- a/include/luerl.hrl +++ b/include/luerl.hrl @@ -1,4 +1,4 @@ -%% Copyright (c) 2013-2019 Robert Virding +%% Copyright (c) 2013-2024 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -25,16 +25,17 @@ envs, %Environment table usds, %Userdata table fncs, %Function table - g, %Global table - %% - stk=[], %Current stack - cs=[], %Current call stack - %% - meta=[], %Data type metatables - rand, %Random state + g, %Global table + %% + stk=[], %Current stack + cs=[], %Current call stack + %% + meta=[], %Data type metatables + rand, %Random state tag, %Unique tag trace_func=none, %Trace function - trace_data %Trace data + trace_data, %Trace data + private=#{} }). %% Table structure. @@ -46,10 +47,10 @@ %% Metatables for atomic datatypes. -record(meta, {nil=nil, - boolean=nil, - number=nil, - string=nil - }). + boolean=nil, + number=nil, + string=nil + }). %% Frames for the call stack. %% Call return frame @@ -111,10 +112,10 @@ body}). %Code block -define(IS_LUAFUNC(F), is_record(F, lua_func)). --record(erl_func,{code}). %Erlang code (fun) +-record(erl_func,{code}). %Erlang code (fun) -define(IS_ERLFUNC(F), is_record(F, erl_func)). --record(erl_mfa,{m,f,a}). %Erlang code (MFA) +-record(erl_mfa,{m,f,a}). %Erlang code (MFA) -define(IS_ERLMFA(F), is_record(F, erl_mfa)). %% Test if it a function, of either sort. @@ -145,28 +146,31 @@ -define(SET_TABLE(N, T, Ts), maps:put(N, T, Ts)). -define(UPD_TABLE(N, Upd, Ts), maps:update_with(N, Upd, Ts)). -define(DEL_TABLE(N, Ts), maps:remove(N, Ts)). +-define(CHK_TABLE(N, Ts), maps:is_key(N, Ts)). -define(FILTER_TABLES(Pred, Ts), maps:filter(Pred, Ts)). -define(FOLD_TABLES(Fun, Acc, Ts), maps:fold(Fun, Acc, Ts)). -endif. -ifdef(TS_USE_ARRAY). -%% Use arrays to handle tables. +%% Use arrays to handle tables. We leave the default value as undefined. -define(MAKE_TABLE(), array:new()). -define(GET_TABLE(N, Ar), array:get(N, Ar)). -define(SET_TABLE(N, T, Ar), array:set(N, T, Ar)). -define(UPD_TABLE(N, Upd, Ar), - array:set(N, (Upd)(array:get(N, Ar)), Ar)). + array:set(N, (Upd)(array:get(N, Ar)), Ar)). -define(DEL_TABLE(N, Ar), array:reset(N, Ar)). +-define(CHK_TABLE(N, Ar), + ((N >= 0) andalso (array:get(N, Ar) =/= undefined))). -define(FILTER_TABLES(Pred, Ar), - ((fun (___Def) -> - ___Fil = fun (___K, ___V) -> - case Pred(___K, ___V) of - true -> ___V; - false -> ___Def - end - end, - array:sparse_map(___Fil, Ar) - end)(array:default(Ar)))). + ((fun (___Def) -> + ___Fil = fun (___K, ___V) -> + case Pred(___K, ___V) of + true -> ___V; + false -> ___Def + end + end, + array:sparse_map(___Fil, Ar) + end)(array:default(Ar)))). -define(FOLD_TABLES(Fun, Acc, Ar), array:sparse_foldl(Fun, Acc, Ar)). -endif. @@ -177,6 +181,7 @@ -define(SET_TABLE(N, T, Ts), orddict:store(N, T, Ts)). -define(UPD_TABLE(N, Upd, Ts), orddict:update(N, Upd, Ts)). -define(DEL_TABLE(N, Ts), orddict:erase(N, Ts)). +-define(CHK_TABLE(N, Ts), orddict:is_key(N, Ts)). -define(FILTER_TABLES(Pred, Ts), orddict:filter(Pred, Ts)). -define(FOLD_TABLES(Fun, Acc, Ts), orddict:fold(Fun, Acc, Ts)). -endif. @@ -188,8 +193,9 @@ -define(SET_TABLE(N, T, Pd), put(N, T)). -define(UPD_TABLE(N, Upd, Pd), put(N, (Upd)(get(N)))). -define(DEL_TABLE(N, Pd), erase(N)). --define(FILTER_TABLES(Pred, Pd), Pd). %This needs work --define(FOLD_TABLES(Fun, Acc, Pd), Pd). %This needs work +-define(CHK_TABLE(N, Pd), (get(N) =/= undefined)). +-define(FILTER_TABLES(Pred, Pd), Pd). %This needs work +-define(FOLD_TABLES(Fun, Acc, Pd), Pd). %This needs work -endif. -ifdef(TS_USE_ETS). @@ -198,13 +204,13 @@ -define(GET_TABLE(N, E), ets:lookup_element(E, N, 2)). -define(SET_TABLE(N, T, E), begin ets:insert(E, {N,T}), E end). -define(UPD_TABLE(N, Upd, E), - begin ets:update_element(E, N, {2,(Upd)(ets:lookup_element(E, N, 2))}), - E end). + begin ets:update_element(E, N, {2,(Upd)(ets:lookup_element(E, N, 2))}), + E end). -define(DEL_TABLE(N, E), begin ets:delete(E, N), E end). --define(FILTER_TABLES(Pred, E), E). %This needs work +-define(FILTER_TABLES(Pred, E), E). %This needs work -define(FOLD_TABLES(Fun, Acc, E), - ets:foldl(fun ({___K, ___T}, ___Acc) -> Fun(___K, ___T, ___Acc) end, - Acc, E)). + ets:foldl(fun ({___K, ___T}, ___Acc) -> Fun(___K, ___T, ___Acc) end, + Acc, E)). -endif. %% Define CATCH to handle deprecated get_stacktrace/0 diff --git a/src/luerl.erl b/src/luerl.erl index 95c78e0..5f92f10 100644 --- a/src/luerl.erl +++ b/src/luerl.erl @@ -47,7 +47,7 @@ -export([externalize/1,internalize/1]). %% Storing and retrieving private data --export([put_private/3,get_private/2]). +-export([put_private/3,get_private/2,delete_private/2]). %% init() -> State. @@ -514,9 +514,15 @@ internalize(S) -> %% State. %% get_private(Key, State) -> %% Value. +%% delete_private(Key, State) -> +%% Value. put_private(Key, Value, S) -> Private = maps:put(Key, Value, S#luerl.private), S#luerl{private=Private}. get_private(Key, S) -> maps:get(Key, S#luerl.private). + +delete_private(Key, S) -> + Private = maps:remove(Key, S#luerl.private), + S#luerl{private=Private}. diff --git a/test/luerl_tests.erl b/test/luerl_tests.erl index 73b6c28..dc026eb 100644 --- a/test/luerl_tests.erl +++ b/test/luerl_tests.erl @@ -47,4 +47,6 @@ private_test() -> State1 = luerl:init(), State2 = luerl:put_private(secret, <<"mysecret">>, State1), ?assertMatch(<<"mysecret">>, luerl:get_private(secret, State2)), - ?assertException(error, {badkey, missing}, luerl:get_private(missing, State2)). + ?assertException(error, {badkey, missing}, luerl:get_private(missing, State2)), + State3 = luerl:delete_private(secret, State2), + ?assertException(error, {badkey, secret}, luerl:get_private(secret, State3)).