Rev 1149 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1149 | diamond | 1 | archiver.obj экспортирует две функции для распаковки deflate-данных. |
6673 | IgorA | 2 | А также функции: deflateInit, deflateInit2, deflateReset, deflate, |
3 | deflateEnd для упаковки deflate-данных, сделанные на основе свободно |
||
4 | распространяемой библиотеки zlib. |
||
1149 | diamond | 5 | |
6 | Первая: deflate_unpack |
||
7 | Объявление в стиле Си: void* __stdcall deflate_unpack(const void* data, unsigned* pLength); |
||
8 | Аргументы: |
||
9 | data - указатель на упакованные данные |
||
10 | pLength - указатель на переменную длины: |
||
11 | на входе *pLength должно содержать длину входных данных data, |
||
12 | на выходе *pLength заполнится длиной выходных данных |
||
13 | Возвращаемое значение: |
||
14 | указатель на распакованные данные, NULL при нехватке памяти |
||
15 | память выделяет сам распаковщик, освободить её можно стандартной |
||
16 | функцией 68.13 |
||
17 | Пример вызова из ассемблерного кода: |
||
18 | ; пусть esi = указатель на данные, ecx = длина упакованных данных |
||
19 | push ecx ; переменная *pLength будет в стеке |
||
20 | push esp ; а вот и указатель на неё pLength |
||
21 | push esi ; а это данные |
||
22 | call [deflate_unpack] |
||
23 | pop ecx ; вытолкнем из стека переменную *pLength |
||
24 | ; два аргумента вытолкнет сама deflate_unpack |
||
25 | ; теперь eax = указатель на распакованные данные, ecx = их длина |
||
26 | |||
27 | Вторая: deflate_unpack2 |
||
28 | Объявление в стиле Си: void* __stdcall deflate_unpack2(const void* get_next_chunk, void* parameter, unsigned* pUnpackedLength); |
||
29 | void* __stdcall get_next_chunk(void* parameter, unsigned* pLength); |
||
30 | Аргументы: |
||
31 | get_next_chunk - указатель на функцию, возвращающую указатель и длину |
||
32 | очередного блока упакованных данных; когда данные |
||
33 | заканчиваются, должна возвращать NULL (при корректных |
||
34 | упакованных данных такой ситуации не может быть в принципе, |
||
35 | при некорректных данных если функция вернула NULL, то |
||
36 | дальнейших вызовов не будет) |
||
37 | parameter - сущность, которая не используется самим распаковщиком |
||
38 | и без изменений передаётся в get_next_chunk |
||
39 | (если callback-функции она тоже не нужна, можно передавать |
||
40 | в этом параметре всё, что угодно) |
||
41 | pUnpackedLength - указатель на переменную, куда будет записана |
||
42 | длина распакованных данных |
||
43 | Возвращаемое значение: |
||
44 | указатель на распакованные данные, NULL при нехватке памяти |
||
45 | память выделяет сам распаковщик, освободить её можно стандартной |
||
46 | функцией 68.13 |
||
47 | Пример вызова из ассемблерного кода: |
||
48 | push eax ; выделяем в стеке переменную для *pUnpackedLength |
||
49 | ; поскольку значение неважно, короче и быстрее всего |
||
50 | ; сделать это однобайтовым push <регистр> |
||
51 | push esp ; а вот и сам указатель pUnpackedLength |
||
52 | push esi ; какой-нибудь параметр |
||
53 | push deflate_callback |
||
54 | call [deflate_unpack2] |
||
55 | pop ecx ; выталкиваем UnpackedLength |
||
56 | ; как и в первом случае, eax = указатель на распакованные данные, ecx = размер |
||
57 | |||
58 | ... |
||
59 | |||
60 | ; а это функция получения следующего куска упакованных данных |
||
61 | deflate_callback: |
||
62 | ; если нужен параметр, то достать его можно так: |
||
63 | ; mov esi, [esp+4] ; esi = параметр |
||
64 | ; тут какие-то действия |
||
65 | ; и вот результат |
||
66 | mov ecx, [esp+8] ; в [ecx] нужно записать длину |
||
67 | mov [ecx], length |
||
68 | mov eax, buffer |
||
69 | ret 8 |
||
6673 | IgorA | 70 | |
71 | Алгоритм для упаковки данных: |
||
72 | 1) Вызов функции deflateInit или deflateInit2. |
||
73 | 2) Разбиение входного потока данных на порции по 64 Кб. |
||
74 | Для каждого блока в 64 Кб в цикле должен делаться вызов функции deflate. |
||
75 | За один вызов функции deflate сжатых данных образуется не более 16 Кб. |
||
76 | Т. е. если сжимаемых данных менее 16 Кб, то их можно упаковать за один вызов deflate. |
||
77 | Если сжимаемых данных менее 64 Кб, то их можно упаковать организовав один цикл с вызовом deflate. |
||
78 | Если сжимаемых данных более 64 Кб, то их можно упаковать организовав двойной цикл с вызовом deflate. |
||
79 | 3) Вызов функции deflateEnd для очистки памяти. |
||
80 | Замечания: |
||
81 | Большие уровни сжатия пока что не поддерживаются. |
||
82 | Функция deflate не коректно работает с параметром Z_NO_FLUSH. |
||
83 | (Пока проблема не устранена рекомендуется всегда ставить Z_FINISH)регистр> |