kolibrios-fun/programs/fs/kfar/trunk/kfar_arc/archiver_deflate.txt
IgorA 22c6f65977 merge libraries 'archiver.obj' and 'zlib.obj'
git-svn-id: svn://kolibrios.org@6673 a494cfbc-eb01-0410-851d-a64ba20cac60
2016-11-04 19:29:50 +00:00

84 lines
3.7 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

archiver.obj экспортирует две функции для распаковки deflate-данных.
А также функции: deflateInit, deflateInit2, deflateReset, deflate,
deflateEnd для упаковки deflate-данных, сделанные на основе свободно
распространяемой библиотеки zlib.
Первая: deflate_unpack
Объявление в стиле Си: void* __stdcall deflate_unpack(const void* data, unsigned* pLength);
Аргументы:
data - указатель на упакованные данные
pLength - указатель на переменную длины:
на входе *pLength должно содержать длину входных данных data,
на выходе *pLength заполнится длиной выходных данных
Возвращаемое значение:
указатель на распакованные данные, NULL при нехватке памяти
память выделяет сам распаковщик, освободить её можно стандартной
функцией 68.13
Пример вызова из ассемблерного кода:
; пусть esi = указатель на данные, ecx = длина упакованных данных
push ecx ; переменная *pLength будет в стеке
push esp ; а вот и указатель на неё pLength
push esi ; а это данные
call [deflate_unpack]
pop ecx ; вытолкнем из стека переменную *pLength
; два аргумента вытолкнет сама deflate_unpack
; теперь eax = указатель на распакованные данные, ecx = их длина
Вторая: deflate_unpack2
Объявление в стиле Си: void* __stdcall deflate_unpack2(const void* get_next_chunk, void* parameter, unsigned* pUnpackedLength);
void* __stdcall get_next_chunk(void* parameter, unsigned* pLength);
Аргументы:
get_next_chunk - указатель на функцию, возвращающую указатель и длину
очередного блока упакованных данных; когда данные
заканчиваются, должна возвращать NULL (при корректных
упакованных данных такой ситуации не может быть в принципе,
при некорректных данных если функция вернула NULL, то
дальнейших вызовов не будет)
parameter - сущность, которая не используется самим распаковщиком
и без изменений передаётся в get_next_chunk
(если callback-функции она тоже не нужна, можно передавать
в этом параметре всё, что угодно)
pUnpackedLength - указатель на переменную, куда будет записана
длина распакованных данных
Возвращаемое значение:
указатель на распакованные данные, NULL при нехватке памяти
память выделяет сам распаковщик, освободить её можно стандартной
функцией 68.13
Пример вызова из ассемблерного кода:
push eax ; выделяем в стеке переменную для *pUnpackedLength
; поскольку значение неважно, короче и быстрее всего
; сделать это однобайтовым push <регистр>
push esp ; а вот и сам указатель pUnpackedLength
push esi ; какой-нибудь параметр
push deflate_callback
call [deflate_unpack2]
pop ecx ; выталкиваем UnpackedLength
; как и в первом случае, eax = указатель на распакованные данные, ecx = размер
...
; а это функция получения следующего куска упакованных данных
deflate_callback:
; если нужен параметр, то достать его можно так:
; mov esi, [esp+4] ; esi = параметр
; тут какие-то действия
; и вот результат
mov ecx, [esp+8] ; в [ecx] нужно записать длину
mov [ecx], length
mov eax, buffer
ret 8
Алгоритм для упаковки данных:
1) Вызов функции deflateInit или deflateInit2.
2) Разбиение входного потока данных на порции по 64 Кб.
Для каждого блока в 64 Кб в цикле должен делаться вызов функции deflate.
За один вызов функции deflate сжатых данных образуется не более 16 Кб.
Т. е. если сжимаемых данных менее 16 Кб, то их можно упаковать за один вызов deflate.
Если сжимаемых данных менее 64 Кб, то их можно упаковать организовав один цикл с вызовом deflate.
Если сжимаемых данных более 64 Кб, то их можно упаковать организовав двойной цикл с вызовом deflate.
3) Вызов функции deflateEnd для очистки памяти.
Замечания:
Большие уровни сжатия пока что не поддерживаются.
Функция deflate не коректно работает с параметром Z_NO_FLUSH.
(Пока проблема не устранена рекомендуется всегда ставить Z_FINISH)