File: unijp.erl

package info (click to toggle)
libunicode-japanese-perl 0.50-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 3,376 kB
  • sloc: ansic: 30,821; perl: 5,635; erlang: 224; makefile: 191
file content (140 lines) | stat: -rw-r--r-- 2,887 bytes parent folder | download | duplicates (2)
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.