22c6f65977
git-svn-id: svn://kolibrios.org@6673 a494cfbc-eb01-0410-851d-a64ba20cac60
84 lines
3.7 KiB
Plaintext
84 lines
3.7 KiB
Plaintext
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)
|