synaicnv.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. {==============================================================================|
  2. | Project : Ararat Synapse | 001.001.000 |
  3. |==============================================================================|
  4. | Content: ICONV support for Win32, Linux and .NET |
  5. |==============================================================================|
  6. | Copyright (c)2004-2008, Lukas Gebauer |
  7. | All rights reserved. |
  8. | |
  9. | Redistribution and use in source and binary forms, with or without |
  10. | modification, are permitted provided that the following conditions are met: |
  11. | |
  12. | Redistributions of source code must retain the above copyright notice, this |
  13. | list of conditions and the following disclaimer. |
  14. | |
  15. | Redistributions in binary form must reproduce the above copyright notice, |
  16. | this list of conditions and the following disclaimer in the documentation |
  17. | and/or other materials provided with the distribution. |
  18. | |
  19. | Neither the name of Lukas Gebauer nor the names of its contributors may |
  20. | be used to endorse or promote products derived from this software without |
  21. | specific prior written permission. |
  22. | |
  23. | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
  24. | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
  25. | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
  26. | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
  27. | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
  28. | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
  29. | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
  30. | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
  31. | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
  32. | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
  33. | DAMAGE. |
  34. |==============================================================================|
  35. | The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
  36. | Portions created by Lukas Gebauer are Copyright (c)2004-2008. |
  37. | All Rights Reserved. |
  38. |==============================================================================|
  39. | Contributor(s): |
  40. |==============================================================================|
  41. | History: see HISTORY.HTM from distribution package |
  42. | (Found at URL: http://www.ararat.cz/synapse/) |
  43. |==============================================================================}
  44. {$IFDEF FPC}
  45. {$MODE DELPHI}
  46. {$ENDIF}
  47. {$H+}
  48. {:@abstract(LibIconv support)
  49. This unit is Pascal interface to LibIconv library for charset translations.
  50. LibIconv is loaded dynamicly on-demand. If this library is not found in system,
  51. requested LibIconv function just return errorcode.
  52. }
  53. unit synaicnv;
  54. interface
  55. uses
  56. {$IFDEF CIL}
  57. System.Runtime.InteropServices,
  58. System.Text,
  59. {$ENDIF}
  60. synafpc,
  61. {$IFNDEF WIN32}
  62. {$IFNDEF FPC}
  63. Libc,
  64. {$ENDIF}
  65. SysUtils;
  66. {$ELSE}
  67. Windows;
  68. {$ENDIF}
  69. const
  70. {$IFNDEF WIN32}
  71. DLLIconvName = 'libiconv.so';
  72. {$ELSE}
  73. DLLIconvName = 'iconv.dll';
  74. {$ENDIF}
  75. type
  76. size_t = Cardinal;
  77. {$IFDEF CIL}
  78. iconv_t = IntPtr;
  79. {$ELSE}
  80. iconv_t = Pointer;
  81. {$ENDIF}
  82. argptr = iconv_t;
  83. var
  84. iconvLibHandle: TLibHandle = 0;
  85. function SynaIconvOpen(const tocode, fromcode: Ansistring): iconv_t;
  86. function SynaIconvOpenTranslit(const tocode, fromcode: Ansistring): iconv_t;
  87. function SynaIconvOpenIgnore(const tocode, fromcode: Ansistring): iconv_t;
  88. function SynaIconv(cd: iconv_t; inbuf: AnsiString; var outbuf: AnsiString): integer;
  89. function SynaIconvClose(var cd: iconv_t): integer;
  90. function SynaIconvCtl(cd: iconv_t; request: integer; argument: argptr): integer;
  91. function IsIconvloaded: Boolean;
  92. function InitIconvInterface: Boolean;
  93. function DestroyIconvInterface: Boolean;
  94. const
  95. ICONV_TRIVIALP = 0; // int *argument
  96. ICONV_GET_TRANSLITERATE = 1; // int *argument
  97. ICONV_SET_TRANSLITERATE = 2; // const int *argument
  98. ICONV_GET_DISCARD_ILSEQ = 3; // int *argument
  99. ICONV_SET_DISCARD_ILSEQ = 4; // const int *argument
  100. implementation
  101. uses SyncObjs;
  102. {$IFDEF CIL}
  103. [DllImport(DLLIconvName, CharSet = CharSet.Ansi,
  104. SetLastError = False, CallingConvention= CallingConvention.cdecl,
  105. EntryPoint = 'libiconv_open')]
  106. function _iconv_open(tocode: string; fromcode: string): iconv_t; external;
  107. [DllImport(DLLIconvName, CharSet = CharSet.Ansi,
  108. SetLastError = False, CallingConvention= CallingConvention.cdecl,
  109. EntryPoint = 'libiconv')]
  110. function _iconv(cd: iconv_t; var inbuf: IntPtr; var inbytesleft: size_t;
  111. var outbuf: IntPtr; var outbytesleft: size_t): size_t; external;
  112. [DllImport(DLLIconvName, CharSet = CharSet.Ansi,
  113. SetLastError = False, CallingConvention= CallingConvention.cdecl,
  114. EntryPoint = 'libiconv_close')]
  115. function _iconv_close(cd: iconv_t): integer; external;
  116. [DllImport(DLLIconvName, CharSet = CharSet.Ansi,
  117. SetLastError = False, CallingConvention= CallingConvention.cdecl,
  118. EntryPoint = 'libiconvctl')]
  119. function _iconvctl(cd: iconv_t; request: integer; argument: argptr): integer; external;
  120. {$ELSE}
  121. type
  122. Ticonv_open = function(tocode: pAnsichar; fromcode: pAnsichar): iconv_t; cdecl;
  123. Ticonv = function(cd: iconv_t; var inbuf: pointer; var inbytesleft: size_t;
  124. var outbuf: pointer; var outbytesleft: size_t): size_t; cdecl;
  125. Ticonv_close = function(cd: iconv_t): integer; cdecl;
  126. Ticonvctl = function(cd: iconv_t; request: integer; argument: argptr): integer; cdecl;
  127. var
  128. _iconv_open: Ticonv_open = nil;
  129. _iconv: Ticonv = nil;
  130. _iconv_close: Ticonv_close = nil;
  131. _iconvctl: Ticonvctl = nil;
  132. {$ENDIF}
  133. var
  134. IconvCS: TCriticalSection;
  135. Iconvloaded: boolean = false;
  136. function SynaIconvOpen (const tocode, fromcode: Ansistring): iconv_t;
  137. begin
  138. {$IFDEF CIL}
  139. try
  140. Result := _iconv_open(tocode, fromcode);
  141. except
  142. on Exception do
  143. Result := iconv_t(-1);
  144. end;
  145. {$ELSE}
  146. if InitIconvInterface and Assigned(_iconv_open) then
  147. Result := _iconv_open(PAnsiChar(tocode), PAnsiChar(fromcode))
  148. else
  149. Result := iconv_t(-1);
  150. {$ENDIF}
  151. end;
  152. function SynaIconvOpenTranslit (const tocode, fromcode: Ansistring): iconv_t;
  153. begin
  154. Result := SynaIconvOpen(tocode + '//IGNORE//TRANSLIT', fromcode);
  155. end;
  156. function SynaIconvOpenIgnore (const tocode, fromcode: Ansistring): iconv_t;
  157. begin
  158. Result := SynaIconvOpen(tocode + '//IGNORE', fromcode);
  159. end;
  160. function SynaIconv (cd: iconv_t; inbuf: AnsiString; var outbuf: AnsiString): integer;
  161. var
  162. {$IFDEF CIL}
  163. ib, ob: IntPtr;
  164. ibsave, obsave: IntPtr;
  165. l: integer;
  166. {$ELSE}
  167. ib, ob: Pointer;
  168. {$ENDIF}
  169. ix, ox: size_t;
  170. begin
  171. {$IFDEF CIL}
  172. l := Length(inbuf) * 4;
  173. ibsave := IntPtr.Zero;
  174. obsave := IntPtr.Zero;
  175. try
  176. ibsave := Marshal.StringToHGlobalAnsi(inbuf);
  177. obsave := Marshal.AllocHGlobal(l);
  178. ib := ibsave;
  179. ob := obsave;
  180. ix := Length(inbuf);
  181. ox := l;
  182. _iconv(cd, ib, ix, ob, ox);
  183. Outbuf := Marshal.PtrToStringAnsi(obsave, l);
  184. setlength(Outbuf, l - ox);
  185. Result := Length(inbuf) - ix;
  186. finally
  187. Marshal.FreeCoTaskMem(ibsave);
  188. Marshal.FreeHGlobal(obsave);
  189. end;
  190. {$ELSE}
  191. if InitIconvInterface and Assigned(_iconv) then
  192. begin
  193. setlength(Outbuf, Length(inbuf) * 4);
  194. ib := Pointer(inbuf);
  195. ob := Pointer(Outbuf);
  196. ix := Length(inbuf);
  197. ox := Length(Outbuf);
  198. _iconv(cd, ib, ix, ob, ox);
  199. setlength(Outbuf, cardinal(Length(Outbuf)) - ox);
  200. Result := Cardinal(Length(inbuf)) - ix;
  201. end
  202. else
  203. begin
  204. Outbuf := '';
  205. Result := 0;
  206. end;
  207. {$ENDIF}
  208. end;
  209. function SynaIconvClose(var cd: iconv_t): integer;
  210. begin
  211. if cd = iconv_t(-1) then
  212. begin
  213. Result := 0;
  214. Exit;
  215. end;
  216. {$IFDEF CIL}
  217. try;
  218. Result := _iconv_close(cd)
  219. except
  220. on Exception do
  221. Result := -1;
  222. end;
  223. cd := iconv_t(-1);
  224. {$ELSE}
  225. if InitIconvInterface and Assigned(_iconv_close) then
  226. Result := _iconv_close(cd)
  227. else
  228. Result := -1;
  229. cd := iconv_t(-1);
  230. {$ENDIF}
  231. end;
  232. function SynaIconvCtl (cd: iconv_t; request: integer; argument: argptr): integer;
  233. begin
  234. {$IFDEF CIL}
  235. Result := _iconvctl(cd, request, argument)
  236. {$ELSE}
  237. if InitIconvInterface and Assigned(_iconvctl) then
  238. Result := _iconvctl(cd, request, argument)
  239. else
  240. Result := 0;
  241. {$ENDIF}
  242. end;
  243. function InitIconvInterface: Boolean;
  244. begin
  245. IconvCS.Enter;
  246. try
  247. if not IsIconvloaded then
  248. begin
  249. {$IFDEF CIL}
  250. IconvLibHandle := 1;
  251. {$ELSE}
  252. IconvLibHandle := LoadLibrary(PChar(DLLIconvName));
  253. {$ENDIF}
  254. if (IconvLibHandle <> 0) then
  255. begin
  256. {$IFNDEF CIL}
  257. _iconv_open := GetProcAddress(IconvLibHandle, PAnsiChar(AnsiString('libiconv_open')));
  258. _iconv := GetProcAddress(IconvLibHandle, PAnsiChar(AnsiString('libiconv')));
  259. _iconv_close := GetProcAddress(IconvLibHandle, PAnsiChar(AnsiString('libiconv_close')));
  260. _iconvctl := GetProcAddress(IconvLibHandle, PAnsiChar(AnsiString('libiconvctl')));
  261. {$ENDIF}
  262. Result := True;
  263. Iconvloaded := True;
  264. end
  265. else
  266. begin
  267. //load failed!
  268. if IconvLibHandle <> 0 then
  269. begin
  270. {$IFNDEF CIL}
  271. FreeLibrary(IconvLibHandle);
  272. {$ENDIF}
  273. IconvLibHandle := 0;
  274. end;
  275. Result := False;
  276. end;
  277. end
  278. else
  279. //loaded before...
  280. Result := true;
  281. finally
  282. IconvCS.Leave;
  283. end;
  284. end;
  285. function DestroyIconvInterface: Boolean;
  286. begin
  287. IconvCS.Enter;
  288. try
  289. Iconvloaded := false;
  290. if IconvLibHandle <> 0 then
  291. begin
  292. {$IFNDEF CIL}
  293. FreeLibrary(IconvLibHandle);
  294. {$ENDIF}
  295. IconvLibHandle := 0;
  296. end;
  297. {$IFNDEF CIL}
  298. _iconv_open := nil;
  299. _iconv := nil;
  300. _iconv_close := nil;
  301. _iconvctl := nil;
  302. {$ENDIF}
  303. finally
  304. IconvCS.Leave;
  305. end;
  306. Result := True;
  307. end;
  308. function IsIconvloaded: Boolean;
  309. begin
  310. Result := IconvLoaded;
  311. end;
  312. initialization
  313. begin
  314. IconvCS:= TCriticalSection.Create;
  315. end;
  316. finalization
  317. begin
  318. {$IFNDEF CIL}
  319. DestroyIconvInterface;
  320. {$ENDIF}
  321. IconvCS.Free;
  322. end;
  323. end.