Difference between revisions of "XML Decoders/ru"

From Lazarus wiki
Jump to navigationJump to search
Line 33: Line 33:
 
  procedure Cleanup(Context: Pointer); stdcall;
 
  procedure Cleanup(Context: Pointer); stdcall;
  
If <code>GetDecoder</code> sets the <code>Decoder.Cleanup</code> member, it is called by reader once, after processing of the current entity is finished. As the name suggests, the decoder should then free all resources it allocated.
+
Если функция <code>GetDecoder</code> установила поле <code>Decoder.Cleanup</code>, то Reader вызывается один раз, после чего текущий процесс завершается. Как видно из названия, декодер должен освободить все занятые ресурсы.
  
The value of <code>Decoder.Context</code> is passed to <code>Decode</code> and <code>Cleanup</code> procedures each time they are called. The reader does not assign any meaning to this value.
+
Значение <code>Decoder.Context</code> устанавливается для <code>Decode</code> и <code>Cleanup</code> процедур при каждом вызове. Reader сам не присваивает значение этому полю.
  
 
==== Декодирование ====
 
==== Декодирование ====

Revision as of 10:04, 17 January 2010

XML декодеры

Начиная с ревизии SVN 12582, XMLReader в состоянии обработать данные в любой кодировке при использовании внешних декодеров. Эта статья - краткое описание, как оно работает.

Доступные декодеры

В настоящее время доступен декодер, который использует libiconv. У него есть две различные реализации:

1. Модуль xmliconv.pas, который использует существующий пакет iconvenc и предназначен для операционных систем Linux, FreeBSD и Darwin.

2. Модуль xmliconv_windows.pas для Windows. Он связан с библиотекой iconv.dll, которую Вы должны распространить вместе с приложением.

Структура декодера

Интерфейс с внешними декодерами сделан в простом процедурном стиле. Для написания декодера по существу используют следующие три процедуры:

  1. GetDecoder
  2. Decode
  3. Cleanup (опционально)

Вот краткое описание:

Получение декодера

function GetDecoder(const AEncoding: string; out Decoder: TDecoder): Boolean; stdcall;

Во время инициализации программы декодер регистрирует себя, вызывая процедуру XMLRead.RegisterDecoder, которой в качестве параметра передаётся функция GetDecoder.

Всякий раз, когда XMLReader сталкивается с меткой кодирования, которую он не может обработать сам, то вызывает все по очереди зарегистрированные функцией GetDecoder декодеры, пока один из них не возвратит True. Параметры функции GetDecoder - названия кодировок и запись типа TDecoder, которую должна заполнить функция. Название кодировок ограничено символами из набора ['A'..'Z', 'a'..'z', '0'.. '9', '.', '-,' _'] вне зависимости от регистра. Если декодер поддерживает данную кодировку, функция должна установить по крайней мере поле Decode в записи Decoder и возвратить True. Установка других полей записи Decoder является необязательным.

Очистка

procedure Cleanup(Context: Pointer); stdcall;

Если функция GetDecoder установила поле Decoder.Cleanup, то Reader вызывается один раз, после чего текущий процесс завершается. Как видно из названия, декодер должен освободить все занятые ресурсы.

Значение Decoder.Context устанавливается для Decode и Cleanup процедур при каждом вызове. Reader сам не присваивает значение этому полю.

Декодирование

function Decode(Context: Pointer; InBuf: PChar; var InCnt: Cardinal;
                OutBuf: PWideChar; var OutCnt: Cardinal): Integer; stdcall;

The Decode function does the main job. It should convert the input data pointed by InBuf into UTF-16 in the current platform endianness and place it into OutBuf. The size of input buffer is supplied in InCnt, the space avaliable in output buffer is in OutCnt.

The important difference to note is that InCnt is given in bytes, while OutCnt is in WideChars.

The function must decrement InCnt and OutCnt according to the amount of data it processes. Each processed character decrements OutCnt by one (or by two in case the surrogate pair is written); the amount of InCnt decrement depends on the actual encoding.

No assumptions should be made about initial size of buffers: for example, the reader may call decoder with only a few bytes in input buffer. The decoder function then should return zero indicating nothing is processed, and the reader will fetch more input and call decoder again.

The function should return positive value if it had processed something, zero if it had not (e.g. because no space available in either input or output buffer), and negative value in cause the input data contains illegal sequence. In the future, there may be attempt to categorize the decoding errors, but currently any negative return simply aborts the reader with the 'Decoding error' message.

In case of error in input data the decoder should still decrement OutCnt to reflect the number of successfully processed characters. This will be used by reader to provide location information in the exception error message.