2 %%%----------------------------------------------------------------------
4 %%% Author : Torbjorn Tornkvist <tobbe@bluetail.com>
5 %%% Purpose : iconv support
6 %%% Created : 23 Mar 2004 by <tobbe@bluetail.com>
9 %%%----------------------------------------------------------------------
10 -behaviour(gen_server
).
11 -export([start
/0, start_link
/0, open
/2, conv
/2, close
/1]).
13 %% gen_server callbacks
14 -export([init
/1, handle_call
/3, handle_cast
/2, handle_info
/2,
15 terminate
/2, code_change
/3]).
17 -record(state
, {port
}).
22 -define(IV_CLOSE
, $c
).
25 -define(DRV_NAME
, "iconv_drv").
26 -define(SERVER
, ?MODULE
).
28 %%%----------------------------------------------------------------------
30 %%%----------------------------------------------------------------------
32 gen_server:start({local
, ?SERVER
}, ?MODULE
, [], []).
35 gen_server:start_link({local
, ?SERVER
}, ?MODULE
, [], []).
37 %%open(To, From) -> {ok, ballen};
39 gen_server:call(?SERVER
, {open
, l2b(To
), l2b(From
)}, infinity
).
41 %%conv(Cd, String) -> {ok, l2b(String)};
42 conv(Cd
, String
) when binary(Cd
) ->
43 gen_server:call(?SERVER
, {conv
, Cd
, l2b(String
)}, infinity
).
46 close(Cd
) when binary(Cd
) ->
47 gen_server:call(?SERVER
, {close
, Cd
}, infinity
).
49 %%%----------------------------------------------------------------------
50 %%% Callback functions from gen_server
51 %%%----------------------------------------------------------------------
53 %%----------------------------------------------------------------------
55 %% Returns: {ok, State} |
56 %% {ok, State, Timeout} |
59 %%----------------------------------------------------------------------
62 Path
= code:priv_dir(iconv
),
63 erl_ddll:load_driver(Path
, ?DRV_NAME
),
64 Port
= open_port({spawn, ?DRV_NAME
}, [binary]),
65 {ok
, #state
{port
= Port
}}.
67 %%----------------------------------------------------------------------
68 %% Func: handle_call/3
69 %% Returns: {reply, Reply, State} |
70 %% {reply, Reply, State, Timeout} |
72 %% {noreply, State, Timeout} |
73 %% {stop, Reason, Reply, State} | (terminate/2 is called)
74 %% {stop, Reason, State} (terminate/2 is called)
75 %%----------------------------------------------------------------------
76 handle_call({open
, To
, From
}, _
, S
) ->
79 Msg
= <<?IV_OPEN
,ToLen:16,To
/binary,FromLen:16,From
/binary>>,
80 Reply
= call_drv(S#state
.port
, Msg
),
83 handle_call({conv
, Cd
, Buf
}, _
, S
) ->
86 Msg
= <<?IV_CONV
,CdLen:16,Cd
/binary,BufLen:16,Buf
/binary>>,
87 Reply
= call_drv(S#state
.port
, Msg
),
90 handle_call({close
, Cd
}, _
, S
) ->
92 Msg
= <<?IV_CLOSE
,CdLen:16,Cd
/binary>>,
93 Reply
= call_drv(S#state
.port
, Msg
),
96 call_drv(Port
, Msg
) ->
97 erlang:port_command(Port
, [Msg
]),
104 {Port
, value
, Bin
} ->
106 {Port
, error
, ErrAtom
} ->
112 %%----------------------------------------------------------------------
113 %% Func: handle_cast/2
114 %% Returns: {noreply, State} |
115 %% {noreply, State, Timeout} |
116 %% {stop, Reason, State} (terminate/2 is called)
117 %%----------------------------------------------------------------------
118 handle_cast(_Msg
, State
) ->
121 %%----------------------------------------------------------------------
122 %% Func: handle_info/2
123 %% Returns: {noreply, State} |
124 %% {noreply, State, Timeout} |
125 %% {stop, Reason, State} (terminate/2 is called)
126 %%----------------------------------------------------------------------
127 handle_info(_Info
, State
) ->
130 %%----------------------------------------------------------------------
132 %% Purpose: Shutdown the server
133 %% Returns: any (ignored by gen_server)
134 %%----------------------------------------------------------------------
135 terminate(_Reason
, _State
) ->
139 code_change(_
, _
, _
) ->
142 %%%----------------------------------------------------------------------
143 %%% Internal functions
144 %%%----------------------------------------------------------------------
147 case lists:zf(fun(Ebin
) ->
148 Priv
= Ebin
++ "/../priv/",
149 case file:read_file_info(Priv
++ File
) of
150 {ok
, _
} -> {true
, Priv
};
153 end, code:get_path()) of
157 error_logger:format("Error: ~s not found in code path\n", [File
]),
161 l2b(L
) when list(L
) -> list_to_binary(L
);
162 l2b(B
) when binary(B
) -> B
.