Merge branch 'pu'
[jungerl.git] / lib / iconv / src / iconv.erl
blob60622344aaa8895ff80c5c94b586f4eee824f576
1 -module(iconv).
2 %%%----------------------------------------------------------------------
3 %%% File : iconv.erl
4 %%% Author : Torbjorn Tornkvist <tobbe@bluetail.com>
5 %%% Purpose : iconv support
6 %%% Created : 23 Mar 2004 by <tobbe@bluetail.com>
7 %%%
8 %%% $Id$
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}).
19 %%% op codes
20 -define(IV_OPEN, $o).
21 -define(IV_CONV, $v).
22 -define(IV_CLOSE, $c).
25 -define(DRV_NAME, "iconv_drv").
26 -define(SERVER, ?MODULE).
28 %%%----------------------------------------------------------------------
29 %%% API
30 %%%----------------------------------------------------------------------
31 start() ->
32 gen_server:start({local, ?SERVER}, ?MODULE, [], []).
34 start_link() ->
35 gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
37 %%open(To, From) -> {ok, ballen};
38 open(To, From) ->
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).
45 %%close(Cd) -> ok;
46 close(Cd) when binary(Cd) ->
47 gen_server:call(?SERVER, {close, Cd}, infinity).
49 %%%----------------------------------------------------------------------
50 %%% Callback functions from gen_server
51 %%%----------------------------------------------------------------------
53 %%----------------------------------------------------------------------
54 %% Func: init/1
55 %% Returns: {ok, State} |
56 %% {ok, State, Timeout} |
57 %% ignore |
58 %% {stop, Reason}
59 %%----------------------------------------------------------------------
60 init([]) ->
61 erl_ddll:start(),
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} |
71 %% {noreply, State} |
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) ->
77 ToLen = size(To),
78 FromLen = size(From),
79 Msg = <<?IV_OPEN,ToLen:16,To/binary,FromLen:16,From/binary>>,
80 Reply = call_drv(S#state.port, Msg),
81 {reply, Reply, S};
83 handle_call({conv, Cd, Buf}, _, S) ->
84 CdLen = size(Cd),
85 BufLen = size(Buf),
86 Msg = <<?IV_CONV,CdLen:16,Cd/binary,BufLen:16,Buf/binary>>,
87 Reply = call_drv(S#state.port, Msg),
88 {reply, Reply, S};
90 handle_call({close, Cd}, _, S) ->
91 CdLen = size(Cd),
92 Msg = <<?IV_CLOSE,CdLen:16,Cd/binary>>,
93 Reply = call_drv(S#state.port, Msg),
94 {reply, Reply, S}.
96 call_drv(Port, Msg) ->
97 erlang:port_command(Port, [Msg]),
98 recv(Port).
100 recv(Port) ->
101 receive
102 {Port, ok} ->
104 {Port, value, Bin} ->
105 {ok,Bin};
106 {Port, error, ErrAtom} ->
107 {error, ErrAtom}
108 end.
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) ->
119 {noreply, 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) ->
128 {noreply, State}.
130 %%----------------------------------------------------------------------
131 %% Func: terminate/2
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 %%%----------------------------------------------------------------------
146 load_path(File) ->
147 case lists:zf(fun(Ebin) ->
148 Priv = Ebin ++ "/../priv/",
149 case file:read_file_info(Priv ++ File) of
150 {ok, _} -> {true, Priv};
151 _ -> false
153 end, code:get_path()) of
154 [Dir|_] ->
155 {ok, Dir};
156 [] ->
157 error_logger:format("Error: ~s not found in code path\n", [File]),
158 {error, enoent}
159 end.
161 l2b(L) when list(L) -> list_to_binary(L);
162 l2b(B) when binary(B) -> B.