1% ----------------------------------------------------------------------------- 2% unijp.erl 3% ----------------------------------------------------------------------------- 4% Mastering programmed by YAMASHINA Hio 5% 6% Copyright 2007 YAMASHINA Hio 7% ----------------------------------------------------------------------------- 8 9% ----------------------------------------------------------------------------- 10%% @author YAMASHINA Hio <hio@hio.jp> 11%% @copyright 2008 YAMASHINA Hio 12%% @version 0.01 13%% @doc Unicode::Japanese binding 14%% == SUPPORTED ENCODINGS == 15%% These options are available for `Icode' argument of {@link new/3} and {@link set/2}. 16%% <ul> 17%% <li>`utf8'</li> 18%% <li>`sjis'</li> 19%% <li>`eucjp'</li> 20%% <li>`jis'</li> 21%% </ul> 22%% @end 23% ----------------------------------------------------------------------------- 24 25-module(unijp). 26-export([start/0, stop/0]). 27-export([version_str/0]). 28-export([version_tuple/0]). 29-export([conv/3]). 30-export([test/0]). 31 32-define(SHAREDLIB, "unijp_driver"). 33-define(PKGNAME, unijp). 34-define(REGNAME, unijp). 35 36-define(PORT_VERSION_STR, 1). 37-define(PORT_VERSION_TUPLE, 2). 38-define(PORT_CONV_3, 3). 39 40test(Name,Fun) -> 41 io:format("~s ...~n", [Name]), 42 Ret = Fun(), 43 io:format("~s: ~p~n", [Name, Ret]), 44 Ret. 45test() -> 46 test(start, fun()-> start() end), 47 test(version_str, fun()-> version_str() end), 48 test(version_tuple, fun()-> version_tuple() end), 49 test(conv, fun()-> conv("utf8", "utf8", "text") end), 50 test(conv, fun()-> conv("utf8", "ucs4", "ts") end), 51 test(conv, fun()-> conv("utf8", "ucs4", "text") end), 52 io:format("ok.~n"), 53 ok. 54 55% ----------------------------------------------------------------------------- 56% version_str(). 57%% @spec version_str() -> string() 58%% @doc get version number as string. 59version_str() -> 60 Result = erlang:port_call(whereis(?REGNAME), ?PORT_VERSION_STR, []), 61 {ok, VersionStr} = Result, 62 VersionStr. 63 64% ----------------------------------------------------------------------------- 65% version_tuple(). 66%% @spec version_tuple() -> {int(),int(),int()} 67%% @doc get version number as tuple of integers. 68version_tuple() -> 69 Result = erlang:port_call(whereis(?REGNAME), ?PORT_VERSION_TUPLE, []), 70 {ok, {Major,Minor,Patch}} = Result, 71 {Major,Minor,Patch}. 72 73% ----------------------------------------------------------------------------- 74% conv(From, To, Source). 75%% @spec conv(From, To, Source) -> string() 76%% From = atom() 77%% To = atom() 78%% Source = iolist() 79%% @doc convert string Source from From to To. 80conv(From, To, Source) -> 81 Bin = iolist_to_binary(Source), 82 Result = erlang:port_call(whereis(?REGNAME), ?PORT_CONV_3, {From,To,Bin}), 83 {ok, Converted} = Result, 84 Converted. 85 86% ----------------------------------------------------------------------------- 87% start. 88% 89%% @spec start()->term() 90%% @doc start port driver 91start() -> 92 my_start(whereis(?REGNAME)). 93 94%% @spec my_start(Port)->pod() 95%% Port = undefined | port() 96%% @private 97my_start(undefined) -> 98 % io:format("start: begin trans..~n"), 99 global:trans({unijp_start, self()}, fun()-> 100 case whereis(?REGNAME) of 101 undefined -> 102 % io:format("start: real start~n"), 103 Pid = my_spawn_server(), 104 % io:format("start: register: ~p (registered:~p)~n", [Pid, whereis(?REGNAME)]), 105 Pid; 106 Pid -> 107 % io:format("start: found in tran ~p~n", [Pid]), 108 Pid 109 end 110 end); 111my_start(Pid) -> 112 % io:format("start: exists: ~p~n", [Pid]), 113 Pid. 114 115%% @spec my_spawn_server()->pid() 116%% @private 117%% @doc spawn server process. 118my_spawn_server() -> 119 % io:format("spawn server ...~n"), 120 Parent = self(), 121 Daemon = spawn(fun()->my_server(Parent) end), 122 Port = receive 123 {Daemon, Recv} -> Recv 124 % after 3000 -> exit(timeout) 125 after 3000*60 -> exit(timeout) 126 end, 127 Port. 128 129%% @spec my_server(Parent)->void() 130%% Parent = pid() 131%% @private 132%% @doc unijp daemon, main. 133my_server(Parent) -> 134 % io:format("server proc ...~n"), 135 Port = my_open_port(), 136 register(?REGNAME, Port), 137 register(unijp_daemon, self()), 138 Parent ! {self(), Port}, 139 my_server_loop([]). 140 141%% @spec my_open_port() -> port() 142%% @private 143%% @doc open port procedure. 144my_open_port()-> 145 % io:format("load_driver ...~n"), 146 case erl_ddll:load_driver(code:priv_dir(?PKGNAME), ?SHAREDLIB) of 147 ok -> ok; 148 {error, already_loaded} -> ok; 149 Any -> exit({error, {could_not_load_driver, Any}}) 150 end, 151 % io:format("open_port ...~n"), 152 Port = open_port({spawn, ?SHAREDLIB}, [binary]), 153 % io:format("open_port ~p on ~p~n", [Port, self()]), 154 Port. 155 156%% @spec my_server_loop(PortList)->void() 157%% PortList = [port()] 158%% @private 159%% @doc loop forever to keep driver/port instances. 160my_server_loop(PortList)-> 161 % io:format("my_server_loop ~p(~p)~n", [self(), PortList]), 162 receive 163 { Caller, close } when is_pid(Caller) -> 164 Caller ! ok; 165 { Caller, find_port } when is_pid(Caller) -> 166 my_server_find_port(Caller, PortList); 167 { Caller, release_port, Port } when is_pid(Caller) -> 168 my_server_loop([Port|PortList]); 169 _Any -> 170 my_server_loop(PortList) 171 end. 172 173my_server_find_port(Caller, []) -> 174 my_server_find_port(Caller, [my_open_port()]); 175my_server_find_port(Caller, [Port|PortList]) -> 176 Caller ! { find_port, Port }, 177 my_server_loop(PortList). 178 179% ----------------------------------------------------------------------------- 180% stop. 181% 182%% @spec stop() -> ok 183%% @doc stop unijp port service. 184stop() -> 185 case whereis(unijp_daemon) of 186 undefined -> 187 ok; 188 Port -> 189 Port ! { self(), close }, 190 receive 191 ok -> ok 192 after 10000 -> 193 exit(noreply) 194 end 195 end. 196 197% ----------------------------------------------------------------------------- 198% End of Module. 199% ----------------------------------------------------------------------------- 200