1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
-module(unijp).
-export([ start/0 ]).
-export([ stop/0 ]).
-export([ stop/1 ]).
-export([version_string/0]).
-export([version_tuple/0]).
-export([conv_binary/3]).
-export([version_str/0]). % compat for 0.0.49.
-export([conv/3]). % compat for 0.0.49.
-export_type([charcode/0]).
-type charcode() :: atom().
-spec start() -> pid().
start() ->
case whereis(unijp) of
undefined ->
start_2();
Pid ->
Pid
end.
start_2() ->
Self = self(),
Ref = make_ref(),
Pid = proc_lib:spawn(fun() -> server_init(Self, Ref) end ),
receive
Ref ->
Pid;
{Ref, {error, Reason}} ->
error({unijp_start, Reason})
after 10*1000 ->
error({unijp_start, timeout})
end.
-spec stop() -> ok.
stop() ->
case whereis(unijp) of
undefined ->
ok;
Pid ->
stop(Pid)
end.
-spec stop(pid()) -> ok.
stop(Pid) ->
Pid ! { self(), close },
Ref = erlang:monitor(process, Pid),
receive
ok ->
receive
{'DOWN', Ref, process, Pid, normal} ->
ok;
{'DOWN', Ref, process, Pid, Info} ->
error_logger:error_msg("unijp:stop received abnomal exit: ~p~n", [Info]),
ok
after 1000 ->
exit(noreply)
end
after 10000 ->
exit(noreply)
end.
-spec version_string() -> string().
version_string() ->
unijp_nif:version_string().
-spec version_tuple() -> {non_neg_integer(), non_neg_integer(), non_neg_integer()}.
version_tuple() ->
unijp_nif:version_tuple().
-spec conv(charcode() | iodata(), charcode() | iodata(), iodata()) -> string().
conv(From, To, Text) ->
conv_compat(From, To, Text).
conv_compat(From, To, Text) ->
From_2 = if
is_atom(From) ->
From;
true ->
unijp_nif:decode_charcode(iolist_to_binary(From))
end,
To_2 = if
is_atom(To) ->
To;
true ->
unijp_nif:decode_charcode(iolist_to_binary(To))
end,
Text_2 = iolist_to_binary(Text),
Bin = unijp_nif:conv(From_2, To_2, Text_2),
binary_to_list(Bin).
-spec conv_binary(charcode(), charcode(), binary()) -> binary().
conv_binary(From, To, Text) ->
unijp_nif:conv(From, To, Text).
% compat for 0.0.49.
-spec version_str() -> string().
version_str() ->
unijp_nif:version_string().
server_init(FromPid, Ref) ->
try
register(unijp, self()),
{module, unijp_nif} = code:ensure_loaded(unijp_nif),
FromPid ! Ref,
ok
of
ok ->
server_loop()
catch
Class:Reason ->
StackTrace = erlang:get_stacktrace(),
error_logger:error_msg("unijp:server_init aborted ~p:~p~n ~p~n", [Class, Reason, StackTrace]),
FromPid ! {Ref, {error, {Class, Reason, StackTrace}}}
end.
server_loop() ->
try
server_loop_2()
catch
Class:Reason ->
StackTrace = erlang:get_stacktrace(),
error_logger:error_msg("unijp:server_loop aborted ~p:~p~n ~p~n", [Class, Reason, StackTrace])
end.
server_loop_2() ->
receive
{FromPid, close} ->
FromPid ! ok,
ok;
X ->
error_logger:error_msg("unijp:server_loop received ~p~n", [X]),
server_loop_2()
end.
|