%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1997-2009. 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([name_server_loop/1,
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() ->
start_server(asn1_ns, asn1ct_name,name_server_loop,[[]]).
stop() -> stop_server(asn1_ns).
name_server_loop(Vars) ->
%% io:format("name -- ~w~n",[Vars]),
receive
{From,{current,Variable}} ->
From ! {asn1_ns,get_curr(Vars,Variable)},
name_server_loop(Vars);
{From,{pop,Variable}} ->
From ! {asn1_ns,done},
name_server_loop(pop_var(Vars,Variable));
{From,{push,Variable}} ->
From ! {asn1_ns,done},
name_server_loop(push_var(Vars,Variable));
{From,{delete,Variable}} ->
From ! {asn1_ns,done},
name_server_loop(delete_var(Vars,Variable));
{From,{new,Variable}} ->
From ! {asn1_ns,done},
name_server_loop(new_var(Vars,Variable));
{From,{prev,Variable}} ->
From ! {asn1_ns,get_prev(Vars,Variable)},
name_server_loop(Vars);
{From,{next,Variable}} ->
From ! {asn1_ns,get_next(Vars,Variable)},
name_server_loop(Vars);
{From,stop} ->
unregister(asn1_ns),
From ! {asn1_ns,stopped},
exit(normal)
end.
active(V) ->
case curr(V) of
nil -> false;
_ -> true
end.
req(Req) ->
asn1_ns ! {self(), Req},
receive {asn1_ns, Reply} -> Reply end.
pop(V) -> req({pop,V}).
push(V) -> req({push,V}).
clear() -> req(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.
stop_server(Name) ->
stop_server(Name, whereis(Name)).
stop_server(_Name, undefined) -> stopped;
stop_server(Name, _Pid) ->
Name ! {self(), stop},
receive {Name, _} -> stopped end.
start_server(Name,Mod,Fun,Args) ->
case whereis(Name) of
undefined ->
case catch register(Name, spawn(Mod,Fun, Args)) of
{'EXIT',{badarg,_}} ->
start_server(Name,Mod,Fun,Args);
_ ->
ok
end;
_Pid ->
already_started
end.