123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- {==============================================================================|
- | Project : Ararat Synapse | 001.001.002 |
- |==============================================================================|
- | Content: ICONV support for Win32, OS/2, Linux and .NET |
- |==============================================================================|
- | Copyright (c)2004-2013, Lukas Gebauer |
- | All rights reserved. |
- | |
- | Redistribution and use in source and binary forms, with or without |
- | modification, are permitted provided that the following conditions are met: |
- | |
- | Redistributions of source code must retain the above copyright notice, this |
- | list of conditions and the following disclaimer. |
- | |
- | Redistributions in binary form must reproduce the above copyright notice, |
- | this list of conditions and the following disclaimer in the documentation |
- | and/or other materials provided with the distribution. |
- | |
- | Neither the name of Lukas Gebauer nor the names of its contributors may |
- | be used to endorse or promote products derived from this software without |
- | specific prior written permission. |
- | |
- | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
- | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
- | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
- | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
- | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
- | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
- | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
- | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
- | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
- | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
- | DAMAGE. |
- |==============================================================================|
- | The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
- | Portions created by Lukas Gebauer are Copyright (c)2004-2013. |
- | All Rights Reserved. |
- |==============================================================================|
- | Contributor(s): |
- | Tomas Hajny (OS2 support) |
- |==============================================================================|
- | History: see HISTORY.HTM from distribution package |
- | (Found at URL: http://www.ararat.cz/synapse/) |
- |==============================================================================}
- {$IFDEF FPC}
- {$MODE DELPHI}
- {$ENDIF}
- {$H+}
- //old Delphi does not have MSWINDOWS define.
- {$IFDEF WIN32}
- {$IFNDEF MSWINDOWS}
- {$DEFINE MSWINDOWS}
- {$ENDIF}
- {$ENDIF}
- {:@abstract(LibIconv support)
- This unit is Pascal interface to LibIconv library for charset translations.
- LibIconv is loaded dynamicly on-demand. If this library is not found in system,
- requested LibIconv function just return errorcode.
- }
- unit synaicnv;
- interface
- uses
- {$IFDEF CIL}
- System.Runtime.InteropServices,
- System.Text,
- {$ENDIF}
- synafpc,
- {$IFNDEF MSWINDOWS}
- {$IFNDEF FPC}
- Libc,
- {$ENDIF}
- SysUtils;
- {$ELSE}
- Windows;
- {$ENDIF}
- const
- {$IFNDEF MSWINDOWS}
- {$IFDEF OS2}
- DLLIconvName = 'iconv.dll';
- {$ELSE OS2}
- DLLIconvName = 'libiconv.so';
- {$ENDIF OS2}
- {$ELSE}
- DLLIconvName = 'iconv.dll';
- {$ENDIF}
- type
- size_t = Cardinal;
- {$IFDEF CIL}
- iconv_t = IntPtr;
- {$ELSE}
- iconv_t = Pointer;
- {$ENDIF}
- argptr = iconv_t;
- var
- iconvLibHandle: TLibHandle = 0;
- function SynaIconvOpen(const tocode, fromcode: Ansistring): iconv_t;
- function SynaIconvOpenTranslit(const tocode, fromcode: Ansistring): iconv_t;
- function SynaIconvOpenIgnore(const tocode, fromcode: Ansistring): iconv_t;
- function SynaIconv(cd: iconv_t; inbuf: AnsiString; var outbuf: AnsiString): integer;
- function SynaIconvClose(var cd: iconv_t): integer;
- function SynaIconvCtl(cd: iconv_t; request: integer; argument: argptr): integer;
- function IsIconvloaded: Boolean;
- function InitIconvInterface: Boolean;
- function DestroyIconvInterface: Boolean;
- const
- ICONV_TRIVIALP = 0; // int *argument
- ICONV_GET_TRANSLITERATE = 1; // int *argument
- ICONV_SET_TRANSLITERATE = 2; // const int *argument
- ICONV_GET_DISCARD_ILSEQ = 3; // int *argument
- ICONV_SET_DISCARD_ILSEQ = 4; // const int *argument
- implementation
- uses SyncObjs;
- {$IFDEF CIL}
- [DllImport(DLLIconvName, CharSet = CharSet.Ansi,
- SetLastError = False, CallingConvention= CallingConvention.cdecl,
- EntryPoint = 'libiconv_open')]
- function _iconv_open(tocode: string; fromcode: string): iconv_t; external;
- [DllImport(DLLIconvName, CharSet = CharSet.Ansi,
- SetLastError = False, CallingConvention= CallingConvention.cdecl,
- EntryPoint = 'libiconv')]
- function _iconv(cd: iconv_t; var inbuf: IntPtr; var inbytesleft: size_t;
- var outbuf: IntPtr; var outbytesleft: size_t): size_t; external;
- [DllImport(DLLIconvName, CharSet = CharSet.Ansi,
- SetLastError = False, CallingConvention= CallingConvention.cdecl,
- EntryPoint = 'libiconv_close')]
- function _iconv_close(cd: iconv_t): integer; external;
- [DllImport(DLLIconvName, CharSet = CharSet.Ansi,
- SetLastError = False, CallingConvention= CallingConvention.cdecl,
- EntryPoint = 'libiconvctl')]
- function _iconvctl(cd: iconv_t; request: integer; argument: argptr): integer; external;
- {$ELSE}
- type
- Ticonv_open = function(tocode: pAnsichar; fromcode: pAnsichar): iconv_t; cdecl;
- Ticonv = function(cd: iconv_t; var inbuf: pointer; var inbytesleft: size_t;
- var outbuf: pointer; var outbytesleft: size_t): size_t; cdecl;
- Ticonv_close = function(cd: iconv_t): integer; cdecl;
- Ticonvctl = function(cd: iconv_t; request: integer; argument: argptr): integer; cdecl;
- var
- _iconv_open: Ticonv_open = nil;
- _iconv: Ticonv = nil;
- _iconv_close: Ticonv_close = nil;
- _iconvctl: Ticonvctl = nil;
- {$ENDIF}
- var
- IconvCS: TCriticalSection;
- Iconvloaded: boolean = false;
- function SynaIconvOpen (const tocode, fromcode: Ansistring): iconv_t;
- begin
- {$IFDEF CIL}
- try
- Result := _iconv_open(tocode, fromcode);
- except
- on Exception do
- Result := iconv_t(-1);
- end;
- {$ELSE}
- if InitIconvInterface and Assigned(_iconv_open) then
- Result := _iconv_open(PAnsiChar(tocode), PAnsiChar(fromcode))
- else
- Result := iconv_t(-1);
- {$ENDIF}
- end;
- function SynaIconvOpenTranslit (const tocode, fromcode: Ansistring): iconv_t;
- begin
- Result := SynaIconvOpen(tocode + '//IGNORE//TRANSLIT', fromcode);
- end;
- function SynaIconvOpenIgnore (const tocode, fromcode: Ansistring): iconv_t;
- begin
- Result := SynaIconvOpen(tocode + '//IGNORE', fromcode);
- end;
- function SynaIconv (cd: iconv_t; inbuf: AnsiString; var outbuf: AnsiString): integer;
- var
- {$IFDEF CIL}
- ib, ob: IntPtr;
- ibsave, obsave: IntPtr;
- l: integer;
- {$ELSE}
- ib, ob: Pointer;
- {$ENDIF}
- ix, ox: size_t;
- begin
- {$IFDEF CIL}
- l := Length(inbuf) * 4;
- ibsave := IntPtr.Zero;
- obsave := IntPtr.Zero;
- try
- ibsave := Marshal.StringToHGlobalAnsi(inbuf);
- obsave := Marshal.AllocHGlobal(l);
- ib := ibsave;
- ob := obsave;
- ix := Length(inbuf);
- ox := l;
- _iconv(cd, ib, ix, ob, ox);
- Outbuf := Marshal.PtrToStringAnsi(obsave, l);
- setlength(Outbuf, l - ox);
- Result := Length(inbuf) - ix;
- finally
- Marshal.FreeCoTaskMem(ibsave);
- Marshal.FreeHGlobal(obsave);
- end;
- {$ELSE}
- if InitIconvInterface and Assigned(_iconv) then
- begin
- setlength(Outbuf, Length(inbuf) * 4);
- ib := Pointer(inbuf);
- ob := Pointer(Outbuf);
- ix := Length(inbuf);
- ox := Length(Outbuf);
- _iconv(cd, ib, ix, ob, ox);
- setlength(Outbuf, cardinal(Length(Outbuf)) - ox);
- Result := Cardinal(Length(inbuf)) - ix;
- end
- else
- begin
- Outbuf := '';
- Result := 0;
- end;
- {$ENDIF}
- end;
- function SynaIconvClose(var cd: iconv_t): integer;
- begin
- if cd = iconv_t(-1) then
- begin
- Result := 0;
- Exit;
- end;
- {$IFDEF CIL}
- try;
- Result := _iconv_close(cd)
- except
- on Exception do
- Result := -1;
- end;
- cd := iconv_t(-1);
- {$ELSE}
- if InitIconvInterface and Assigned(_iconv_close) then
- Result := _iconv_close(cd)
- else
- Result := -1;
- cd := iconv_t(-1);
- {$ENDIF}
- end;
- function SynaIconvCtl (cd: iconv_t; request: integer; argument: argptr): integer;
- begin
- {$IFDEF CIL}
- Result := _iconvctl(cd, request, argument)
- {$ELSE}
- if InitIconvInterface and Assigned(_iconvctl) then
- Result := _iconvctl(cd, request, argument)
- else
- Result := 0;
- {$ENDIF}
- end;
- function InitIconvInterface: Boolean;
- begin
- IconvCS.Enter;
- try
- if not IsIconvloaded then
- begin
- {$IFDEF CIL}
- IconvLibHandle := 1;
- {$ELSE}
- IconvLibHandle := LoadLibrary(PChar(DLLIconvName));
- {$ENDIF}
- if (IconvLibHandle <> 0) then
- begin
- {$IFNDEF CIL}
- _iconv_open := GetProcAddress(IconvLibHandle, PAnsiChar(AnsiString('libiconv_open')));
- _iconv := GetProcAddress(IconvLibHandle, PAnsiChar(AnsiString('libiconv')));
- _iconv_close := GetProcAddress(IconvLibHandle, PAnsiChar(AnsiString('libiconv_close')));
- _iconvctl := GetProcAddress(IconvLibHandle, PAnsiChar(AnsiString('libiconvctl')));
- {$ENDIF}
- Result := True;
- Iconvloaded := True;
- end
- else
- begin
- //load failed!
- if IconvLibHandle <> 0 then
- begin
- {$IFNDEF CIL}
- FreeLibrary(IconvLibHandle);
- {$ENDIF}
- IconvLibHandle := 0;
- end;
- Result := False;
- end;
- end
- else
- //loaded before...
- Result := true;
- finally
- IconvCS.Leave;
- end;
- end;
- function DestroyIconvInterface: Boolean;
- begin
- IconvCS.Enter;
- try
- Iconvloaded := false;
- if IconvLibHandle <> 0 then
- begin
- {$IFNDEF CIL}
- FreeLibrary(IconvLibHandle);
- {$ENDIF}
- IconvLibHandle := 0;
- end;
- {$IFNDEF CIL}
- _iconv_open := nil;
- _iconv := nil;
- _iconv_close := nil;
- _iconvctl := nil;
- {$ENDIF}
- finally
- IconvCS.Leave;
- end;
- Result := True;
- end;
- function IsIconvloaded: Boolean;
- begin
- Result := IconvLoaded;
- end;
- initialization
- begin
- IconvCS:= TCriticalSection.Create;
- end;
- finalization
- begin
- {$IFNDEF CIL}
- DestroyIconvInterface;
- {$ENDIF}
- IconvCS.Free;
- end;
- end.
|