Subversion Repositories Kolibri OS

Rev

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)