%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 1997-2012. 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 %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. %% %% %CopyrightEnd% %% %% -module(asn1ct_name). %%-compile(export_all). -export([start/0, stop/0, push/1, pop/1, curr/1, clear/0, delete/1, active/1, prev/1, next/1, all/1, new/1]). start() -> Parent = self(), case get(?MODULE) of undefined -> put(?MODULE, spawn_link(fun() -> Ref = monitor(process, Parent), name_server_loop({Ref,Parent},[]) end)), ok; _Pid -> already_started end. stop() -> req(stop), erase(?MODULE). name_server_loop({Ref, Parent} = Monitor,Vars) -> %% io:format("name -- ~w~n",[Vars]), receive {From,{current,Variable}} -> From ! {?MODULE,get_curr(Vars,Variable)}, name_server_loop(Monitor,Vars); {From,{pop,Variable}} -> From ! {?MODULE,done}, name_server_loop(Monitor,pop_var(Vars,Variable)); {From,{push,Variable}} -> From ! {?MODULE,done}, name_server_loop(Monitor,push_var(Vars,Variable)); {From,{delete,Variable}} -> From ! {?MODULE,done}, name_server_loop(Monitor,delete_var(Vars,Variable)); {From,{new,Variable}} -> From ! {?MODULE,done}, name_server_loop(Monitor,new_var(Vars,Variable)); {From,{prev,Variable}} -> From ! {?MODULE,get_prev(Vars,Variable)}, name_server_loop(Monitor,Vars); {From,{next,Variable}} -> From ! {?MODULE,get_next(Vars,Variable)}, name_server_loop(Monitor,Vars); {'DOWN', Ref, process, Parent, Reason} -> exit(Reason); {From,stop} -> From ! {?MODULE,stopped} end. active(V) -> case curr(V) of nil -> false; _ -> true end. req(Req) -> get(?MODULE) ! {self(), Req}, receive {?MODULE, Reply} -> Reply after 5000 -> exit(name_server_timeout) end. pop(V) -> req({pop,V}). push(V) -> req({push,V}). clear() -> stop(), start(). curr(V) -> req({current,V}). new(V) -> req({new,V}). delete(V) -> req({delete,V}). prev(V) -> case req({prev,V}) of none -> exit('cant get prev of none'); Rep -> Rep end. next(V) -> case req({next,V}) of none -> exit('cant get next of none'); Rep -> Rep end. all(V) -> Curr = curr(V), if Curr == V -> []; true -> lists:reverse(generate(V,last(Curr),[],0)) end. generate(V,Number,Res,Pos) -> Ell = Pos+1, if Ell > Number -> Res; true -> generate(V,Number,[list_to_atom(lists:concat([V,Ell]))|Res],Ell) end. last(V) -> last2(lists:reverse(atom_to_list(V))). last2(RevL) -> list_to_integer(lists:reverse(get_digs(RevL))). get_digs([H|T]) -> if H < $9+1, H > $0-1 -> [H|get_digs(T)]; true -> [] end. push_var(Vars,Variable) -> case lists:keysearch(Variable,1,Vars) of false -> [{Variable,[0]}|Vars]; {value,{Variable,[Digit|Drest]}} -> NewVars = lists:keydelete(Variable,1,Vars), [{Variable,[Digit,Digit|Drest]}|NewVars] end. pop_var(Vars,Variable) -> case lists:keysearch(Variable,1,Vars) of false -> ok; {value,{Variable,[_Dig]}} -> lists:keydelete(Variable,1,Vars); {value,{Variable,[_Dig|Digits]}} -> NewVars = lists:keydelete(Variable,1,Vars), [{Variable,Digits}|NewVars] end. get_curr([],Variable) -> Variable; get_curr([{Variable,[0|_Drest]}|_Tail],Variable) -> Variable; get_curr([{Variable,[Digit|_Drest]}|_Tail],Variable) -> list_to_atom(lists:concat([Variable,integer_to_list(Digit)])); get_curr([_|Tail],Variable) -> get_curr(Tail,Variable). new_var(Vars,Variable) -> case lists:keysearch(Variable,1,Vars) of false -> [{Variable,[1]}|Vars]; {value,{Variable,[Digit|Drest]}} -> NewVars = lists:keydelete(Variable,1,Vars), [{Variable,[Digit+1|Drest]}|NewVars] end. delete_var(Vars,Variable) -> case lists:keysearch(Variable,1,Vars) of false -> Vars; {value,{Variable,[N]}} when N =< 1 -> lists:keydelete(Variable,1,Vars); {value,{Variable,[Digit|Drest]}} -> case Digit of 0 -> Vars; _ -> NewVars = lists:keydelete(Variable,1,Vars), [{Variable,[Digit-1|Drest]}|NewVars] end end. get_prev(Vars,Variable) -> case lists:keysearch(Variable,1,Vars) of false -> none; {value,{Variable,[Digit|_]}} when Digit =< 1 -> Variable; {value,{Variable,[Digit|_]}} when Digit > 1 -> list_to_atom(lists:concat([Variable, integer_to_list(Digit-1)])); _ -> none end. get_next(Vars,Variable) -> case lists:keysearch(Variable,1,Vars) of false -> list_to_atom(lists:concat([Variable,"1"])); {value,{Variable,[Digit|_]}} when Digit >= 0 -> list_to_atom(lists:concat([Variable, integer_to_list(Digit+1)])); _ -> none end.