mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-10-21 02:04:17 +02:00

* Changed the design of input decoders so they process data by chunks instead of char-by-char. It is much faster, and allows supporting external pluggable decoders. + Interface for external decoders. * ResolvePredefined() is rewritten so it doesn't call CompareMem five times do determine a single char. * ParseCharRef renamed to ParseRef, because it parses entity refs as well. * Added guard conditions to prevent integer overflows in ParseRef. * ContextPush(TXMLCharSource) merged into Initialize(). xmliconv.pas is a new unit, containing an libiconv-based decoder. It depends on existing iconvenc package, and thus supports all platforms that are supported by iconvenc. xmliconv_windows.pas is the variation that allows to use libiconv functionality on Windows (It would require the iconv.dll to be distributed with the application, but since I haven't succeeded yet in writing a native Windows decoder, this is better than nothing). git-svn-id: trunk@12582 -
79 lines
1.9 KiB
ObjectPascal
79 lines
1.9 KiB
ObjectPascal
{
|
|
This file is part of the Free Component Library
|
|
|
|
libiconv-based XML decoder.
|
|
Copyright (c) 2009 by Sergei Gorelkin, sergei_gorelkin@mail.ru
|
|
|
|
See the file COPYING.FPC, included in this distribution,
|
|
for details about the copyright.
|
|
|
|
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 xmliconv;
|
|
|
|
interface
|
|
|
|
implementation
|
|
|
|
uses
|
|
xmlread, iconvenc, unixtype, baseunix, initc;
|
|
|
|
const
|
|
{$ifdef FPC_LITTLE_ENDIAN}
|
|
utf16_encoding = 'UTF-16LE';
|
|
{$else FPC_LITTLE_ENDIAN}
|
|
utf16_encoding = 'UTF-16BE';
|
|
{$endif FPC_LITTLE_ENDIAN}
|
|
|
|
function Iconv_Decode(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar; var OutCnt: Cardinal): Integer; stdcall;
|
|
var
|
|
OutChars: size_t;
|
|
InChars: size_t;
|
|
begin
|
|
OutChars := OutCnt * sizeof(WideChar);
|
|
InChars := InCnt;
|
|
Result := iconv(Context, @InBuf, @InChars, @OutBuf, @OutChars);
|
|
InCnt := InChars;
|
|
OutCnt := OutChars div sizeof(WideChar);
|
|
if Result = -1 then
|
|
begin
|
|
case cerrno of
|
|
// when iconv reports insufficient input or output space, still return
|
|
// a positive number of converted chars
|
|
ESysE2BIG, ESysEINVAL:
|
|
Result := OutCnt - (OutChars div sizeof(WideChar));
|
|
else
|
|
Result := -cerrno;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure Iconv_Cleanup(Context: Pointer); stdcall;
|
|
begin
|
|
iconv_close(Context);
|
|
end;
|
|
|
|
function GetIconvDecoder(const AEncoding: string; out Decoder: TDecoder): Boolean; stdcall;
|
|
var
|
|
f: iconv_t;
|
|
begin
|
|
f := iconv_open(utf16_encoding, PChar(AEncoding));
|
|
if f <> Pointer(-1) then
|
|
begin
|
|
Decoder.Context := f;
|
|
Decoder.Decode := @Iconv_Decode;
|
|
Decoder.Cleanup := @Iconv_Cleanup;
|
|
Result := True;
|
|
end
|
|
else
|
|
Result := False;
|
|
end;
|
|
|
|
initialization
|
|
RegisterDecoder(@GetIconvDecoder);
|
|
|
|
end.
|