summaryrefslogtreecommitdiff
path: root/fpcsrc/packages/fcl-xml/src/xmliconv.pas
blob: 7144b3141a18eb3ba4b589df6e40c79e8e9be809 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
{
    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.