diff options
| author | marco <marco@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2009-04-25 12:10:42 +0000 |
|---|---|---|
| committer | marco <marco@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2009-04-25 12:10:42 +0000 |
| commit | 8ade4b268980f7da3d1cdda9f7efdf8982e6a98c (patch) | |
| tree | 076df155a71794585614f4300fc903e84031a159 /packages/iconvenc | |
| parent | 3bd886747eacfb6bbd987f0c5a9355eaf53762e3 (diff) | |
| download | fpc-8ade4b268980f7da3d1cdda9f7efdf8982e6a98c.tar.gz | |
* iconvenc now also with dynlinking separate. Some fixes for OS X 10.3 and Haiku ported from cwstring
git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@13038 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'packages/iconvenc')
| -rw-r--r-- | packages/iconvenc/Makefile | 132 | ||||
| -rw-r--r-- | packages/iconvenc/Makefile.fpc | 4 | ||||
| -rw-r--r-- | packages/iconvenc/fpmake.pp | 3 | ||||
| -rwxr-xr-x | packages/iconvenc/src/iconvenc.pas | 147 | ||||
| -rwxr-xr-x | packages/iconvenc/src/iconvenc_dyn.pas | 106 | ||||
| -rw-r--r-- | packages/iconvenc/src/iconvert.inc | 60 |
6 files changed, 273 insertions, 179 deletions
diff --git a/packages/iconvenc/Makefile b/packages/iconvenc/Makefile index 4c493ceff0..b73c9bf3d9 100644 --- a/packages/iconvenc/Makefile +++ b/packages/iconvenc/Makefile @@ -1,5 +1,5 @@ # -# Don't edit, this file is generated by FPCMake Version 2.0.0 [2008/10/22] +# Don't edit, this file is generated by FPCMake Version 2.0.0 [2009/04/25] # default: all MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded @@ -265,178 +265,178 @@ PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(F override PACKAGE_NAME=iconvenc override PACKAGE_VERSION=2.2.2 ifeq ($(FULL_TARGET),i386-linux) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-go32v2) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-win32) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-os2) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-freebsd) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-beos) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-haiku) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-netbsd) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-solaris) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-qnx) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-netware) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-openbsd) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-wdosx) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-darwin) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-emx) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-watcom) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-netwlibc) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-wince) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-embedded) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-symbian) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),m68k-linux) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),m68k-freebsd) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),m68k-netbsd) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),m68k-amiga) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),m68k-atari) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),m68k-openbsd) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),m68k-palmos) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),m68k-embedded) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),powerpc-linux) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),powerpc-netbsd) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),powerpc-amiga) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),powerpc-macos) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),powerpc-darwin) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),powerpc-morphos) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),powerpc-embedded) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),sparc-linux) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),sparc-netbsd) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),sparc-solaris) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),sparc-embedded) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),x86_64-linux) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),x86_64-freebsd) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),x86_64-darwin) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),x86_64-win64) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),x86_64-embedded) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),arm-linux) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),arm-palmos) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),arm-darwin) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),arm-wince) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),arm-gba) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),arm-nds) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),arm-embedded) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),arm-symbian) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),powerpc64-linux) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),powerpc64-darwin) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),powerpc64-embedded) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),avr-embedded) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),armeb-linux) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),armeb-embedded) -override TARGET_UNITS+=iconvenc +override TARGET_UNITS+=iconvenc iconvenc_dyn endif ifeq ($(FULL_TARGET),i386-linux) override TARGET_EXAMPLEDIRS+=examples @@ -1213,6 +1213,7 @@ endif ifeq ($(OS_TARGET),go32v2) STATICLIBPREFIX= SHORTSUFFIX=dos +IMPORTLIBPREFIX= endif ifeq ($(OS_TARGET),watcom) STATICLIBPREFIX= @@ -1220,6 +1221,7 @@ OEXT=.obj ASMEXT=.asm SHAREDLIBEXT=.dll SHORTSUFFIX=wat +IMPORTLIBPREFIX= endif ifeq ($(OS_TARGET),linux) BATCHEXT=.sh @@ -1256,6 +1258,7 @@ STATICLIBPREFIX= SHAREDLIBEXT=.dll SHORTSUFFIX=os2 ECHO=echo +IMPORTLIBPREFIX= endif ifeq ($(OS_TARGET),emx) BATCHEXT=.cmd @@ -1264,6 +1267,7 @@ STATICLIBPREFIX= SHAREDLIBEXT=.dll SHORTSUFFIX=emx ECHO=echo +IMPORTLIBPREFIX= endif ifeq ($(OS_TARGET),amiga) EXEEXT= @@ -1303,17 +1307,20 @@ ifeq ($(OS_TARGET),netware) EXEEXT=.nlm STATICLIBPREFIX= SHORTSUFFIX=nw +IMPORTLIBPREFIX=imp endif ifeq ($(OS_TARGET),netwlibc) EXEEXT=.nlm STATICLIBPREFIX= SHORTSUFFIX=nwl +IMPORTLIBPREFIX=imp endif ifeq ($(OS_TARGET),macos) BATCHEXT= EXEEXT= DEBUGSYMEXT=.xcoff SHORTSUFFIX=mac +IMPORTLIBPREFIX=imp endif ifeq ($(OS_TARGET),darwin) BATCHEXT=.sh @@ -1340,14 +1347,17 @@ STATICLIBEXT=.a1 SHAREDLIBEXT=.so1 STATICLIBPREFIX= SHORTSUFFIX=v1 +IMPORTLIBPREFIX= endif ifeq ($(OS_TARGET),go32v2) STATICLIBPREFIX= SHORTSUFFIX=dos +IMPORTLIBPREFIX= endif ifeq ($(OS_TARGET),watcom) STATICLIBPREFIX= SHORTSUFFIX=wat +IMPORTLIBPREFIX= endif ifeq ($(OS_TARGET),linux) BATCHEXT=.sh @@ -1394,6 +1404,7 @@ STATICLIBEXT=.ao2 SHAREDLIBEXT=.dll SHORTSUFFIX=os2 ECHO=echo +IMPORTLIBPREFIX= endif ifeq ($(OS_TARGET),amiga) EXEEXT= @@ -1454,6 +1465,7 @@ STATICLIBEXT=.a SHAREDLIBEXT=.nlm EXEEXT=.nlm SHORTSUFFIX=nw +IMPORTLIBPREFIX=imp endif ifeq ($(OS_TARGET),netwlibc) STATICLIBPREFIX= @@ -1465,6 +1477,7 @@ STATICLIBEXT=.a SHAREDLIBEXT=.nlm EXEEXT=.nlm SHORTSUFFIX=nwl +IMPORTLIBPREFIX=imp endif ifeq ($(OS_TARGET),macos) BATCHEXT= @@ -1476,6 +1489,7 @@ STATICLIBEXT=.a EXEEXT= DEBUGSYMEXT=.xcoff SHORTSUFFIX=mac +IMPORTLIBPREFIX=imp endif endif ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),) diff --git a/packages/iconvenc/Makefile.fpc b/packages/iconvenc/Makefile.fpc index f08930b81a..1e532070a1 100644 --- a/packages/iconvenc/Makefile.fpc +++ b/packages/iconvenc/Makefile.fpc @@ -3,11 +3,11 @@ # [package] -name=iconvenc +name=iconvenc version=2.2.2 [target] -units=iconvenc +units=iconvenc iconvenc_dyn exampledirs=examples [require] diff --git a/packages/iconvenc/fpmake.pp b/packages/iconvenc/fpmake.pp index e8f090f5d3..59f0f3a3c6 100644 --- a/packages/iconvenc/fpmake.pp +++ b/packages/iconvenc/fpmake.pp @@ -28,6 +28,9 @@ begin P.IncludePath.Add('src'); T:=P.Targets.AddUnit('iconvenc.pas'); + T.Dependencies.AddInclude('iconvert.inc'); + T:=P.Targets.AddUnit('iconvenc_dyn.pas'); + T.Dependencies.AddInclude('iconvert.inc'); P.ExamplePath.Add('examples'); P.Targets.AddExampleProgram('iconvtest.pp'); diff --git a/packages/iconvenc/src/iconvenc.pas b/packages/iconvenc/src/iconvenc.pas index d151daf1bd..e90ace9e5d 100755 --- a/packages/iconvenc/src/iconvenc.pas +++ b/packages/iconvenc/src/iconvenc.pas @@ -19,13 +19,9 @@ unit iconvenc; interface {$mode objfpc}{$H+} -{DEFINE LOADDYNAMIC} uses ctypes,unixtype,baseunix, - {$ifdef LOADDYNAMIC} - dl, - {$endif} initc; const @@ -43,135 +39,50 @@ type Ticonv = function(__cd: iconv_t; __inbuf: ppchar; __inbytesleft: psize_t; __outbuf: ppchar; __outbytesleft: psize_t): size_t; cdecl; Ticonv_close = function(__cd: iconv_t): cint; cdecl; -{$IFNDEF LOADDYNAMIC} -{$ifndef Linux} // and other OSes with iconv in libc. -{$linklib iconv} +{$if not defined(linux) and not defined(solaris)} // Linux (and maybe glibc pl + {$if defined(haiku)} + {$linklib textencoding} + {$else} + {$linklib iconv} + {$endif} + {$define useiconv} +{$endif linux} + +Const +{$ifndef useiconv} + libiconvname='c'; // is in libc under Linux. +{$else} + {$ifdef haiku} + libiconvname='textencoding'; // is in libtextencoding under Haiku + {$else} + libiconvname='iconv'; + {$endif} {$endif} -function iconv_open(__tocode: pchar; __fromcode: pchar): iconv_t; cdecl; external; -function iconv (__cd: iconv_t; __inbuf: ppchar; __inbytesleft: psize_t; __outbuf: ppchar; __outbytesleft: psize_t): size_t; cdecl; external; -function iconv_close (__cd: iconv_t): cint; cdecl; external; -var - IconvLibFound: boolean = False; +{$if defined(darwin) and defined(cpupowerpc32)} + iconvprefix='lib'; +{$else} + iconvprefix=''; +{$endif} + +function iconv_open(__tocode: pchar; __fromcode: pchar): iconv_t; cdecl; external libiconvname name iconvprefix+'iconv_open'; +function iconv (__cd: iconv_t; __inbuf: ppchar; __inbytesleft: psize_t; __outbuf: ppchar; __outbytesleft: psize_t): size_t; cdecl; external libiconvname name iconvprefix+'iconv'; +function iconv_close (__cd: iconv_t): cint; cdecl; external libiconvname name iconvprefix+'iconv_close'; -{$ELSE} var - iconv_lib: pointer; - iconv_open: Ticonv_open; - iconv: Ticonv; - iconv_close: Ticonv_close; - IconvLibFound: boolean = true; - -function TryLoadLib(LibName: string; var error: string): boolean; // can be used to load non standard libname -{$endif} + IconvLibFound: boolean = False; function Iconvert(s: string; var res: string; FromEncoding, ToEncoding: string): cint; function InitIconv(var error: string): boolean; implementation -{$IFDEF LOADDYNAMIC} -function TryLoadLib(LibName: string; var error: string): boolean; - - function resolvesymbol (var funcptr; symbol: string): Boolean; - begin - pointer(funcptr) := pointer(dlsym(iconv_lib, pchar(symbol))); - result := assigned(pointer(funcptr)); - if not result then - error := error+#13#10+dlerror(); - end; - -var - res: boolean; -begin - result := false; - Error := Error+#13#10'Trying '+LibName; - iconv_lib := dlopen(pchar(libname), RTLD_NOW); - if Assigned(iconv_lib) then - begin - result := true; - result := result and resolvesymbol(pointer(iconv),'iconv'); - result := result and resolvesymbol(pointer(iconv_open),'iconv_open'); - result := result and resolvesymbol(pointer(iconv_close),'iconv_close'); -// if not res then -// dlclose(iconv_lib); - end else - error:=error+#13#10+dlerror(); -end; - -{$ENDIF} - function InitIconv(var error: string): boolean; begin result := true; - {$ifdef LOADDYNAMIC} - error := ''; - if not TryLoadLib('libc.so.6', error) then - if not TryLoadLib('libiconv.so', error) then - result := false; - {$endif} iconvlibfound := iconvlibfound or result; end; -function Iconvert(S: string; var Res: string; FromEncoding, ToEncoding: string): cint; -var - InLen, OutLen, Offset: size_t; - Src, Dst: pchar; - H: iconv_t; - lerr: cint; - iconvres: size_t; -begin - H := iconv_open(PChar(ToEncoding), PChar(FromEncoding)); - if not assigned(H) then - begin - Res := S; - exit(-1); - end; - - try - SetLength(Res, Length(S)); - InLen := Length(S); - OutLen := Length(Res); - Src := PChar(S); - Dst := PChar(Res); - - while InLen > 0 do - begin - iconvres := iconv(H, @Src, @InLen, @Dst, @OutLen); - if iconvres = size_t(-1) then - begin - lerr := cerrno; - if lerr = ESysEILSEQ then // unknown char, skip - begin - Dst^ := Src^; - Inc(Src); - Inc(Dst); - Dec(InLen); - Dec(OutLen); - end - else - if lerr = ESysE2BIG then - begin - Offset := Dst - PChar(Res); - SetLength(Res, Length(Res)+InLen*2+5); // 5 is minimally one utf-8 char - Dst := PChar(Res) + Offset; - OutLen := Length(Res) - Offset; - end - else - exit(-1) - end; - end; - - // iconv has a buffer that needs flushing, specially if the last char is not #0 - iconv(H, nil, nil, @Dst, @Outlen); - - // trim output buffer - SetLength(Res, Length(Res) - Outlen); - finally - iconv_close(H); - end; - - Result := 0; -end; +{$i iconvert.inc} end. diff --git a/packages/iconvenc/src/iconvenc_dyn.pas b/packages/iconvenc/src/iconvenc_dyn.pas new file mode 100755 index 0000000000..87d6436f21 --- /dev/null +++ b/packages/iconvenc/src/iconvenc_dyn.pas @@ -0,0 +1,106 @@ +{ + This file is part of the Free Pascal run time library. + Copyright (c) 2000 by Marco van de Voort(marco@freepascal.org) + member of the Free Pascal development team + + libiconv header translation + a helper routine + http://wiki.freepascal.org/iconvenc Dynamic version + + See the file COPYING.FPC, included in this distribution, + for details about the copyright. (LGPL) + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +} +unit iconvenc_dyn; + +interface +{$mode objfpc}{$H+} + +uses + ctypes,unixtype,baseunix, + dl, + initc; + +const + n = 1; + +{$ifdef beos} + ESysEILSEQ = EILSEQ; +{$endif} + +type + piconv_t = ^iconv_t; + iconv_t = pointer; + + Ticonv_open = function(__tocode: pchar; __fromcode: pchar): iconv_t; cdecl; + Ticonv = function(__cd: iconv_t; __inbuf: ppchar; __inbytesleft: psize_t; __outbuf: ppchar; __outbytesleft: psize_t): size_t; cdecl; + Ticonv_close = function(__cd: iconv_t): cint; cdecl; + +var + iconv_lib: pointer; + iconv_open: Ticonv_open; + iconv: Ticonv; + iconv_close: Ticonv_close; + IconvLibFound: boolean = true; + +function TryLoadLib(LibName: string; var error: string): boolean; // can be used to load non standard libname +function Iconvert(s: string; var res: string; FromEncoding, ToEncoding: string): cint; +function InitIconv(var error: string): boolean; + +implementation + +function TryLoadLib(LibName: string; var error: string): boolean; + + function resolvesymbol (var funcptr; symbol: string): Boolean; + begin + pointer(funcptr) := pointer(dlsym(iconv_lib, pchar(symbol))); + result := assigned(pointer(funcptr)); + if not result then + error := error+#13#10+dlerror(); + end; + +var + res: boolean; +begin + result := false; + Error := Error+#13#10'Trying '+LibName; + iconv_lib := dlopen(pchar(libname), RTLD_NOW); + if Assigned(iconv_lib) then + begin + result := true; + result := result and resolvesymbol(pointer(iconv),'iconv'); + result := result and resolvesymbol(pointer(iconv_open),'iconv_open'); + result := result and resolvesymbol(pointer(iconv_close),'iconv_close'); + if not result then + begin + result:=true; + result := result and resolvesymbol(pointer(iconv),'libiconv'); + result := result and resolvesymbol(pointer(iconv_open),'libiconv_open'); + result := result and resolvesymbol(pointer(iconv_close),'libiconv_close'); + end; +// if not res then +// dlclose(iconv_lib); + end else + error:=error+#13#10+dlerror(); +end; + + +function InitIconv(var error: string): boolean; +begin + result := true; + error := ''; + if not TryLoadLib('libc.so.6', error) then + if not TryLoadLib('libiconv.so', error) then + {$if defined(haiku)} + if not TryLoadLib('libtextencoding.so', error) then + {$ifend} + result := false; + iconvlibfound := iconvlibfound or result; +end; + +{$i iconvert.inc} + +end. diff --git a/packages/iconvenc/src/iconvert.inc b/packages/iconvenc/src/iconvert.inc new file mode 100644 index 0000000000..bee2a9d2f6 --- /dev/null +++ b/packages/iconvenc/src/iconvert.inc @@ -0,0 +1,60 @@ +function Iconvert(S: string; var Res: string; FromEncoding, ToEncoding: string): cint; +var + InLen, OutLen, Offset: size_t; + Src, Dst: pchar; + H: iconv_t; + lerr: cint; + iconvres: size_t; +begin + H := iconv_open(PChar(ToEncoding), PChar(FromEncoding)); + if not assigned(H) then + begin + Res := S; + exit(-1); + end; + + try + SetLength(Res, Length(S)); + InLen := Length(S); + OutLen := Length(Res); + Src := PChar(S); + Dst := PChar(Res); + + while InLen > 0 do + begin + iconvres := iconv(H, @Src, @InLen, @Dst, @OutLen); + if iconvres = size_t(-1) then + begin + lerr := cerrno; + if lerr = ESysEILSEQ then // unknown char, skip + begin + Dst^ := Src^; + Inc(Src); + Inc(Dst); + Dec(InLen); + Dec(OutLen); + end + else + if lerr = ESysE2BIG then + begin + Offset := Dst - PChar(Res); + SetLength(Res, Length(Res)+InLen*2+5); // 5 is minimally one utf-8 char + Dst := PChar(Res) + Offset; + OutLen := Length(Res) - Offset; + end + else + exit(-1) + end; + end; + + // iconv has a buffer that needs flushing, specially if the last char is not #0 + iconv(H, nil, nil, @Dst, @Outlen); + + // trim output buffer + SetLength(Res, Length(Res) - Outlen); + finally + iconv_close(H); + end; + + Result := 0; +end; |
