Copyright (C) 1995-2005 Jean-loup Gailly и Mark Adler
Эта библиотека поставляется 'как есть', без каких-либо явных или подразумеваемых гарантий. Ни при каких обстоятельствах авторы не несут какой-либо ответственности в случае потери данных вследствие использования данной библиотеки.
Разрешается всем использовать эту библиотеку для любых целей, в том числе и для коммерческих приложений, а также изменять ее и распространять свободно при соблюдении следующих условий:
Это руководство создано на основе zlib.h, автор - piaip , перевел на русский Н.Онищук.
Посетите http://www.zlib.org - официальный сайт библиотеки zlib.
Сжатие может быть выполнено за один проход, если буферы достаточно большие (к примеру, если входной файл проецируется в память), или же сжатие может быть выполнено путем многократных вызовов функции компрессии. В последнем случае приложение должно обеспечить несколько больший входной буфер и возможно больший выходной буфер перед каждым вызовом функции компрессии.
Библиотека также поддерживает чтение и запись файлов в формате gzip (.gz) с интерфейсом похожим на используемый в stdio.
Библиотека не инсталлирует каких-либо хуков, обработчиков сигналов и сообщений. Декодер проверяет структуру компрессованных данных, так что библиотека не рухнет, даже если ей на вход будут поданы искаженные данные.
Если параметр flush выставлен в Z_SYNC_FLUSH, то все уже сжатые данные будут сброшены в выходной буфер, который будет выровнен по байту, т.о. что декомпрессор сможет получить доступ к этим данным в любой момент. (В частности, avail_in выставляется в ноль после вызова, если предварительно не было обеспечено достаточно места в выходном буфере.) Сбрасывание буферов может ухудшить степень сжатия для некоторых алгоритмов, поэтому применять его следует только при необходимости.
Если параметр flush выставлен в Z_FULL_FLUSH, то все буфера сбрасываются также, как и при Z_SYNC_FLUSH, переменная state сбрасывается т.о., что декомпрессия может быть возоблена с этого же место, если предыдущие сжатые данные были повреждены или требуется произвольный доступ к данным. Чрезмерно частое использование Z_FULL_FLUSH может серьезно ухудшить сжатие.
Если deflate завершилась с avail_out == 0, то необходимо вновь вызвать эту же функцию с тем же значением параметра flush и большим размером выходного буфера (с обновленным avail_out), если же сброс выходных буферов прошел успешно (deflate возвращается с ненулевым avail_out).
Если параметр flush выставлен в Z_FINISH, то обработается входной буфер, результат сбросится в выходной буфер и deflate завершится с Z_STREAM_END если было достаточно места в выходном буфере; если deflate завершилась с Z_OK, то необходимо вновь вызвать эту же функцию с Z_FINISH и большим размером выходного буфера (обновленным avail_out) но с теми же входными данными, т.е пока функция не завершится с Z_STREAM_END или не произойдет ошибка. После завершения deflate с результатом Z_STREAM_END, единственными доступными операциями над потоком являются deflateReset или deflateEnd.
Z_FINISH может быть использован сразу после deflateInit если все сжатие может быть выполнено за один вызов. В этом случае значение поля avail_out должно быть на 0.1% больше avail_in плюс 12 байт. Если deflate не вернула Z_STREAM_END, то она должна быть вызвана повторно, как было описано выше.
deflate() выставляет strm-> adler в контрольную сумма adler32 всех всех прочитанных данных (т.е, total_in байт).
deflate() может обновлять data_type если она сможет достоверно определить тип входных данных (Z_ASCII или Z_BINARY). В случае неопределенности данные рассматриваются как бинарные. Это поле является справочным и ни в коем случае не влияет на алгоритмы сжатия.
Функция deflate() возвращает:
Функция deflateEnd возвращает:
В случае ошибки msg может быть выставлена, но будет указывать на статическую строку (которую не нужно освобождать).
Функция inflateInit возвращает:
msg выставляется в NULL, если нет каких-либо сообщений об ошибке. inflateInit не выполняет какой-либо декомпрессии, кроме чтения zlib заголовка, если тот присутствует. Декомпрессия осуществляется функцией inflate(). (Т.о. next_in и avail_in могут быть модифицированы, но next_out и avail_out остаются неизменными.)
Подробная семантика описана ниже. inflate выполняет одно или все действия:
Перед вызовом inflate(), приложение должно убедиться, что как минимум одно из действий возможно, обеспечивая данные для декомпрессии на входе, считывая результаты на выходе, и обновляя соответствующие параметры - next_* и avail_*. Приложение может считывать декомпрессованые данные на выходе когда потребуется, к примеру, когда выходной буфер станет заполнен (т.е. avail_out == 0), или после каждого вызова inflate(). Если inflate вернет Z_OK с нулевым avail_out, то функцию нужно вызвать заново, обеспечив достаточно места в выходно буфере, чтобы в него можно было записать уже декомпресованые данные.
Если параметр flush выставлен в Z_SYNC_FLUSH, то inflate сбрасывает в выходной буфер столько декомпресованых данных, сколько возможно. Поведение функции inflate не определено для значений параметра flush, отличающихся от Z_SYNC_FLUSH или Z_FINISH, хотя текущая реализация в любом случае сбрасывает столько информации в выходной буфер, сколько это возможно
Функция inflate() может вызываться до тех пор, пока не вернет Z_STREAM_END или код ошибки. Однако, если вся декомпрессия может быть произведена за за один вызов, то параметр flush должен быть выставлен в Z_FINISH. В этом случае обрабатывается весь входной буфер и все обработанные данные сбрасываются в выходной; avail_out должен быть достаточно большой, чтобы вместить все декомпресованные данные. (Для этих целей размер несжатых данных может быть сохранен компрессором). Следующая операция над потоком должна быть inflateEnd чтобы сбросить состояние декомпрессии - state. Использование параметра Z_FINISH не является обязательным, но может быть полезным для единичного вызова inflate(), что бы последняя могла оптимизировать скорость и ресурсы для декомпрессии.
Если на этом этапе потребуется словарь (см. inflateSetDictionary ниже), то функция inflate выставит strm->adler в adler32 контрольную сумму выбранного компрессором словаря и вернет Z_NEED_DICT; в противном случае функция выставит strm->adler в adler32 контрольную сумму всех декомпресованных данных (т.е. total_out байт) и вернет Z_OK, Z_STREAM_END или код ошибки, как описано ниже. В конце потока inflate() проверяет на равенство посчитанную ей adler32 контрольную сумму и такую же сумму, посчитанную компрессором и в случае совпадения возвращает Z_STREAM_END.
Функция inflate() возвращает:
Если функция вернет Z_DATA_ERROR, то приложение в последствии может вызвать inflateSync чтобы найти неповрежденный блок для декомпрессии.
Функция inflateEnd возвращает:
В случае ошибки msg может быть выставлена, но будет указывать на статический буфер (который не нужно освобождать).
Параметр method задает метод сжатия. В текущей версии библиотеки должен равняться Z_DEFLATED.
Параметр windowBits является базой двух логарифмов размера окна (размер буфера истории). Должен быть в диапазоне 8..15 для текущей версии библиотеки. Большие значения этого параметра улучшают сжатие и увеличивают объем используемой памяти. При использовании функции deflateInit этот параметр равняется 15.
Параметр memLevel определяет сколько памяти может быть распределено для внутренней переменной сжатия state. memLevel=1 использует минимум мамяти, но выполняется медленно и уменьшает степень сжатия; memLevel=9 использует максимум памяти с оптимальной скоростью сжатия. Значение по умолчанию - 8. Подробности работы с памятью и варианты использования параметров windowBits и memLevel описаны в файле zconf.h.
Параметр strategy определяет алгоритм сжатия. Используйте значение Z_DEFAULT_STRATEGY для обыкновенных данных, Z_FILTERED для данных, обработанных фильтром (или предиктором), или Z_HUFFMAN_ONLY чтобы явно указать к использованию только кодирование по Хаффману (никаких строк вообще). Отфильтрованные данные содержат главным образом малые значения с каким-то случайным распределением. В этом случае в качестве алгоритма сжатия будет использован наилучший - compress. Эффект от применения Z_FILTERED заключается в форсировании кодирования по Хаффману и меньшем использовании строкового сравнения; это что-то среднее между Z_DEFAULT и Z_HUFFMAN_ONLY. Параметр strategy влияет только на степень сжатия.
Функция deflateInit2 возвращает:
msg выставляется в NULL если не было никаких сообщений об ошибках. deflateInit2 не выполняет какой-либо компрессии: это делает deflate().
Словарь должен содержать строки (последовательности байт) которые будут встречаться позже в данных для компрессии. Предпочтительно, чтобы наиболее часто встречающиеся строки располагались ближе к концу словаря. Использование словаря наиболее полезно в случаях, когда данные для сжатия небольшие и могут быть спрогнозированы с хорошей точностью; в этом случае данные могут быть сжаты лучше, если сравнивать с вариантом, при котором пустой словарь.
В зависимости от размера и структуры входных данных deflateInit или deflateInit2 могут фактически игнорировать часть словаря, к примеру, если размер словаря больше, чем размер окна в deflate или deflate2. Т.о. строки, которые чаще встречаются, должны располагаться ближе к концу словаря, а не к началу.
После возвращения из этой функции strm->adler будет выставлен в Adler32 контрольную сумму словаря; декомпрессор впоследствии может использовать это значение для того, чтобы идентифицировать словарь, который был использован компрессором. (Adler32 контрольная сумма считается по всему словарю, даже если компрессор использовал только часть словаря.)
Функция deflateSetDictionary возвращает:
Функция deflateSetDictionary не выполняет какой-либо компрессии, это будет делать deflate().
Эта функция может быть полезна, когда опробуется несколько стратегий сжатия, к примеру, когда входные данные разными способами предварительно обрабатываются. Потоки, которые в последствии окажутся не нужны, требуется освободить с помощью функции deflateEnd. Заметьте, что deflateCopy дублирует внутреннюю переменную state, которая может быть достаточно большой, так что такой подход может оказаться медленным и потребовать больших затрат памяти.
Функция deflateCopy возвращает:
msg остается неизменной и в входном и в выходном потоке.
Функция deflateReset возвращает:
Перед вызовом deflateParams, переменная потока state должна быть инициализирована также как и перед вызовом deflate(), чтобы впоследствии текущий входной поток мог быть сжат и сброшен в выходной буфер. В частности, поле strm->avail_out должно быть не нулевым.
Функция deflateParams возвращает:
The windowBits parameter является базой двух логарифмов максимального размера окна (размер буфера истории). Должен находится в диапазоне от 8..15 для текущей версии библиотеки. Значение по умолчанию - 15, если используется альтернативная версия функции - inflateInit. Если сжатый поток с большим размером окна подается на вход, inflate() вернется с кодом ошибки Z_DATA_ERROR вместо попытки выделить память для большего окна.
Функция inflateInit2 возвращает:
msg выставляется в NULL, если нет каких-либо сообщений об ошибке. inflateInit2 не выполняет какой-либо декомпрессии, кроме чтения zlib заголовка, если тот присутствует. Декомпрессию будет производить inflate(). (Т.о. поля next_in и avail_in могут быть модифицированы, но next_out и avail_out остануться неизменными.)
Функция inflateSetDictionary возвращает:
Функция inflateSetDictionary не выполняет какой-либо декомпрессии, это выполняется последующим вызовом inflate().
Функция inflateSync возвращает:
В случае успеха приложение может сохранить текущий указатель total_in, который будет показывать сколько правильных сжатых данных было обнаружено. В случае ошибки приложение может повторно вызвать inflateSync, подавая на вход новые данные, пока не будет найден неповрежденный фрагмент, или не закончатся данные на входе.
Функция inflateReset возвращает:
Adler-32 контрольная сумма так же надежна, как и посчитанная функцией CRC32, но может быть высчитана намного быстрее. Пример использования:
uLong adler = adler32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { adler = adler32(adler, buffer, length); } if (adler != original_adler) error();
uLong crc = crc32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { crc = crc32(crc, buffer, length); } if (crc != original_crc) error();
typedef struct z_stream_s { Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ uLong total_in; /* total nb of input bytes read so far */ Bytef *next_out; /* next output byte should be put there */ uInt avail_out; /* remaining free space at next_out */ uLong total_out; /* total nb of bytes output so far */ char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ int data_type; /* best guess about the data type: ascii or binary */ uLong adler; /* adler32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream ; typedef z_stream FAR * z_streamp; яПриложение должно обновлять next_in и avail_in когда avail_in сбрасывается в ноль. Также нужно обновлять next_out и avail_out когда avail_out сбрасывается в ноль. Приложение должно инициализировать zalloc, zfree и opaque поля перед вызовом init-функций. Все остальные поля заполняются библиотекой и не должны модифицироваться приложением.
Параметр opaque, подготовленный приложением, будет передаваться в качестве первого параметра при вызове функций zalloc и zfree. Он может быть полезен при более тонком управлении потреблением памяти. Библиотека сжатия ничего о параметре opaque не знает.
zalloc должна вернуть Z_NULL если не смогла выделить достаточно памяти. Если библиотека zlib используется в многопоточном приложении, zalloc и zfree должны быть потокобезопасными.
В 16-битной системе, функции zalloc и zfree должны иметь возможность выделить вплоть до 65536 байт, не понадобиться выделять больше памяти, если будет определен макрос MAXSEG_64K (см.zconf.h). ВНИМАНИЕ: В MSDOS, указатели, возвращаемые zalloc для объектов превышающих 65536 байт *должны* иметь смещение нормализованное относительно 0. Функции выделения памяти по умолчанию из этой библиотеки обеспечивают это (см. zutil.c). Чтобы уменьшить потребление памяти и предотвратить выделение памяти для объектов свыше 64K, путем ухудшения сжатия, скомпилируйте библиотеку с ключом -DMAX_WBITS=14 (см. zconf.h).
Поля total_in и total_out могут пригодится для визуализации процесса сжатия. После сжатия, total_in содержит полный размер несжатых данных и может быть сохранен для использования декомпрессором (для частного случая, когда декомпрессию нужно будет осуществить за один вызов).
#define Z_NO_FLUSH 0 #define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ #define Z_SYNC_FLUSH 2 #define Z_FULL_FLUSH 3 #define Z_FINISH 4 /* Allowed flush values ; see deflate() below for details */ #define Z_OK 0 #define Z_STREAM_END 1 #define Z_NEED_DICT 2 #define Z_ERRNO (-1) #define Z_STREAM_ERROR (-2) #define Z_DATA_ERROR (-3) #define Z_MEM_ERROR (-4) #define Z_BUF_ERROR (-5) #define Z_VERSION_ERROR (-6) /* Return codes for the compression/decompression functions. Negative * values are errors, positive values are used for special but normal events. */ #define Z_NO_COMPRESSION 0 #define Z_BEST_SPEED 1 #define Z_BEST_COMPRESSION 9 #define Z_DEFAULT_COMPRESSION (-1) /* compression levels */ #define Z_FILTERED 1 #define Z_HUFFMAN_ONLY 2 #define Z_DEFAULT_STRATEGY 0 /* compression strategy ; see deflateInit2() below for details */ #define Z_BINARY 0 #define Z_ASCII 1 #define Z_UNKNOWN 2 /* Possible values of the data_type field */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */ #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ #define zlib_version zlibVersion() /* for compatibility with versions less than 1.0.2 */
Прочие функции, которые экспортируются из библиотеки: