Difference between revisions of "XML Decoders/ru"

From Lazarus wiki
Jump to navigationJump to search
(→‎Функция Decode: more improvements)
Line 52: Line 52:
 
Функция должна уменьшить <code>InCnt</code> and <code>OutCnt</code> в соответствии с количеством обработанных данных. Каждый обработанный символ уменьшает <code>OutCnt</code> на единицу (или на 2 в случае, если в буфер записывается суррогатная пара); то, на сколько уменьшается <code>InCnt</code>, зависит от входной кодировки.
 
Функция должна уменьшить <code>InCnt</code> and <code>OutCnt</code> в соответствии с количеством обработанных данных. Каждый обработанный символ уменьшает <code>OutCnt</code> на единицу (или на 2 в случае, если в буфер записывается суррогатная пара); то, на сколько уменьшается <code>InCnt</code>, зависит от входной кодировки.
  
Функция не должна делать каких-либо предположений о начальном размере буферов: для примера, Reader может вызвать декодер с недостаточной длиной входного буфера. В этом случае функция decoder должна возвратить 0, индицируя о том, она ничего не декодировала, после чего reader прочитает дополнительные входные данные и вызовет decoder снова.
+
Функция не должна делать каких-либо предположений о начальном размере буферов: для примера, парсер может вызвать <code>Decode</code> с недостаточной длиной входного буфера. В этом случае <code>Decode</code> должна возвратить 0, индицируя о том, она ничего не декодировала, после чего парсер прочитает дополнительные входные данные и вызовет <code>Decode</code> снова.
  
 
Функция должна возвращать положительный результат, если она что-то обработала, ноль - если нет (по причине отсутствия места во входном или выходном буфере), и отрицательное значение в случае, если входные данные содержат недопустимую последовательность. В настоящее время любое отрицательное значение просто прерывает чтение с сообщением об ошибке декодирования, но в дальнейшем, возможно, будут определены разновидности ошибок.
 
Функция должна возвращать положительный результат, если она что-то обработала, ноль - если нет (по причине отсутствия места во входном или выходном буфере), и отрицательное значение в случае, если входные данные содержат недопустимую последовательность. В настоящее время любое отрицательное значение просто прерывает чтение с сообщением об ошибке декодирования, но в дальнейшем, возможно, будут определены разновидности ошибок.
  
 
В случае обнаружения ошибки во входных данных декодер все равно должен уменьшить значение <code>OutCnt</code> на количество успешно обработанных символов. Это позволяет парсеру сообщать точное расположение ошибки в тексте.
 
В случае обнаружения ошибки во входных данных декодер все равно должен уменьшить значение <code>OutCnt</code> на количество успешно обработанных символов. Это позволяет парсеру сообщать точное расположение ошибки в тексте.

Revision as of 15:46, 18 January 2010

English (en) español (es) русский (ru) 中文(中国大陆)‎ (zh_CN)

XML декодеры

Дополнение к XML_Tutorial/ru.

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

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

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

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

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

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

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

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

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

Функция GetDecoder

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 не является обязательной.

Процедура Cleanup

procedure Cleanup(Context: Pointer); stdcall;

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

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

Функция Decode

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

Функция Decode выполняет основную работу. Она должна преобразовать входные данные, указатель на которые находится в InBuf, в UTF-16 и записать перевод в буфер, на который указывает OutBuf. Размер входного буфера находится в InCnt, а размер буфера вывода находится в OutCnt.

Важное замечание: значение InCnt выражено в bytes, в то время как OutCnt - в WideChars.

Функция должна уменьшить InCnt and OutCnt в соответствии с количеством обработанных данных. Каждый обработанный символ уменьшает OutCnt на единицу (или на 2 в случае, если в буфер записывается суррогатная пара); то, на сколько уменьшается InCnt, зависит от входной кодировки.

Функция не должна делать каких-либо предположений о начальном размере буферов: для примера, парсер может вызвать Decode с недостаточной длиной входного буфера. В этом случае Decode должна возвратить 0, индицируя о том, она ничего не декодировала, после чего парсер прочитает дополнительные входные данные и вызовет Decode снова.

Функция должна возвращать положительный результат, если она что-то обработала, ноль - если нет (по причине отсутствия места во входном или выходном буфере), и отрицательное значение в случае, если входные данные содержат недопустимую последовательность. В настоящее время любое отрицательное значение просто прерывает чтение с сообщением об ошибке декодирования, но в дальнейшем, возможно, будут определены разновидности ошибок.

В случае обнаружения ошибки во входных данных декодер все равно должен уменьшить значение OutCnt на количество успешно обработанных символов. Это позволяет парсеру сообщать точное расположение ошибки в тексте.