класс Zlib::Inflate
Zlib::Inflate — это класс для распаковки сжатых данных. В отличие от Zlib::Deflate, экземпляр этого класса не может дублироваться (клонироваться, дублировать).
Публичные методы класса
static VALUE
rb_inflate_s_inflate(VALUE obj, VALUE src)
{
struct zstream z;
VALUE dst, args[2];
int err;
StringValue(src);
zstream_init_inflate(&z);
err = inflateInit(&z.stream);
if (err != Z_OK) {
raise_zlib_error(err, z.stream.msg);
}
ZSTREAM_READY(&z);
args[0] = (VALUE)&z;
args[1] = src;
dst = rb_ensure(inflate_run, (VALUE)args, zstream_ensure_end, (VALUE)&z);
return dst;
} Распаковывает string. Вызывает исключение Zlib::NeedDict, если для распаковки требуется предварительно заданный словарь.
Этот метод практически эквивалентен следующему коду:
def inflate(string) zstream = Zlib::Inflate.new buf = zstream.inflate(string) zstream.finish zstream.close buf end
См. также Zlib.deflate
static VALUE
rb_inflate_initialize(int argc, VALUE *argv, VALUE obj)
{
struct zstream *z;
VALUE wbits;
int err;
rb_scan_args(argc, argv, "01", &wbits);
TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z);
err = inflateInit2(&z->stream, ARG_WBITS(wbits));
if (err != Z_OK) {
raise_zlib_error(err, z->stream.msg);
}
ZSTREAM_READY(z);
return obj;
} Создает новый поток распаковки для распаковки. window_bits устанавливает размер буфера истории и может принимать следующие значения:
- 0
-
Используйте для распаковки размер окна из заголовка zlib сжатого потока.
- (8..15)
-
Переопределяет размер окна заголовка распаковки в сжатом потоке. Размер окна должен быть больше или равен размеру окна сжатого потока.
- Больше 15
-
Добавьте 32 к window_bits, чтобы включить декодирование zlib и gzip с автоматическим обнаружением заголовков, или добавьте 16, чтобы декодировать только формат gzip (исключение
Zlib::DataErrorбудет вызвано для потока, не являющегося gzip). - (-8..-15)
-
Включает режим распаковки raw deflate, который не будет генерировать значение проверки и не будет искать значения проверки для сравнения в конце потока.
Это используется с другими форматами, которые используют формат сжатия deflate, такими как zip, которые предоставляют свои собственные значения проверки.
Пример
open "compressed.file" do |compressed_io|
zi = Zlib::Inflate.new(Zlib::MAX_WBITS + 32)
begin
open "uncompressed.file", "w+" do |uncompressed_io|
uncompressed_io << zi.inflate(compressed_io.read)
end
ensure
zi.close
end
end
Публичные методы экземпляра
static VALUE
rb_inflate_addstr(VALUE obj, VALUE src)
{
struct zstream *z = get_zstream(obj);
if (ZSTREAM_IS_FINISHED(z)) {
if (!NIL_P(src)) {
StringValue(src);
zstream_append_buffer2(z, src);
}
}
else {
do_inflate(z, src);
if (ZSTREAM_IS_FINISHED(z)) {
zstream_passthrough_input(z);
}
}
return obj;
} То же, что и IO.
static VALUE
rb_inflate_add_dictionary(VALUE obj, VALUE dictionary)
{
VALUE dictionaries = rb_ivar_get(obj, id_dictionaries);
VALUE checksum = do_checksum(1, &dictionary, adler32);
rb_hash_aset(dictionaries, checksum, dictionary);
return obj;
} Предоставляет потоку распаковки словарь, который может потребоваться в будущем. Можно предоставить несколько словарей. Поток распаковки автоматически выберет правильный предоставленный пользователем словарь в зависимости от требуемого словаря потока.
static VALUE
rb_inflate_inflate(int argc, VALUE* argv, VALUE obj)
{
struct zstream *z = get_zstream(obj);
VALUE dst, src, opts, buffer = Qnil;
if (OPTHASH_GIVEN_P(opts)) {
VALUE buf;
rb_get_kwargs(opts, &id_buffer, 0, 1, &buf);
if (buf != Qundef && buf != Qnil) {
buffer = StringValue(buf);
}
}
if (buffer != Qnil) {
if (!(ZSTREAM_REUSE_BUFFER_P(z) && z->buf == buffer)) {
long len = RSTRING_LEN(buffer);
if (len >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
rb_str_modify(buffer);
}
else {
len = ZSTREAM_AVAIL_OUT_STEP_MAX - len;
rb_str_modify_expand(buffer, len);
}
rb_str_set_len(buffer, 0);
z->flags |= ZSTREAM_REUSE_BUFFER;
z->buf = buffer;
}
} else if (ZSTREAM_REUSE_BUFFER_P(z)) {
z->flags &= ~ZSTREAM_REUSE_BUFFER;
z->buf = Qnil;
}
rb_scan_args(argc, argv, "10", &src);
if (ZSTREAM_IS_FINISHED(z)) {
if (NIL_P(src)) {
dst = zstream_detach_buffer(z);
}
else {
StringValue(src);
zstream_append_buffer2(z, src);
if (ZSTREAM_REUSE_BUFFER_P(z)) {
dst = rb_str_resize(buffer, 0);
} else {
dst = rb_str_new(0, 0);
}
}
}
else {
do_inflate(z, src);
dst = zstream_detach_buffer(z);
if (ZSTREAM_IS_FINISHED(z)) {
zstream_passthrough_input(z);
}
}
return dst;
} Вводит deflate_string в поток распаковки и возвращает вывод из потока. Вызов этого метода одновременно очищает входной и выходной буферы потока. Если строка является nil, этот метод завершает поток, подобно Zlib::ZStream#finish.
Если задан блок, последовательные распакованные фрагменты из deflate_string передаются в блок, и возвращается nil.
Если в качестве ключевого аргумента :buffer задано значение, отличное от nil:
-
Ключевой аргумент :buffer должен быть
Stringи будет использоваться в качестве выходного буфера. Использование этого параметра позволяет повторно использовать память, необходимую при распаковке. -
При отсутствии блока возвращаемое значение будет тем же объектом, что и ключевой аргумент :buffer.
-
При наличии блока передаваемые фрагменты будут иметь то же значение, что и ключевой аргумент :buffer.
Вызывает исключение Zlib::NeedDict, если для распаковки требуется предварительно заданный словарь. Set словарь с помощью Zlib::Inflate#set_dictionary, а затем вызовите этот метод снова со строкой-пустышкой, чтобы очистить поток:
inflater = Zlib::Inflate.new begin out = inflater.inflate compressed rescue Zlib::NeedDict # ensure the dictionary matches the stream's required dictionary raise unless inflater.adler == Zlib.adler32(dictionary) inflater.set_dictionary dictionary inflater.inflate '' end # ... inflater.close
См. также Zlib::Inflate.new
static VALUE
rb_inflate_set_dictionary(VALUE obj, VALUE dic)
{
struct zstream *z = get_zstream(obj);
VALUE src = dic;
int err;
StringValue(src);
err = inflateSetDictionary(&z->stream,
(Bytef*)RSTRING_PTR(src), RSTRING_LENINT(src));
if (err != Z_OK) {
raise_zlib_error(err, z->stream.msg);
}
return dic;
} Устанавливает предварительно заданный словарь и возвращает string. Этот метод доступен только после того, как было вызвано исключение Zlib::NeedDict. Подробнее см. в zlib.h.
static VALUE
rb_inflate_sync(VALUE obj, VALUE src)
{
struct zstream *z = get_zstream(obj);
StringValue(src);
return zstream_sync(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src));
} Вводит string в конец буфера входных данных и пропускает данные до тех пор, пока не будет найден полный момент очистки. Если точка найдена в буфере, этот метод очищает буфер и возвращает false. В противном случае возвращает true, и последующие данные полного момента очистки сохраняются в буфере.
static VALUE
rb_inflate_sync_point_p(VALUE obj)
{
struct zstream *z = get_zstream(obj);
int err;
err = inflateSyncPoint(&z->stream);
if (err == 1) {
return Qtrue;
}
if (err != Z_OK) {
raise_zlib_error(err, z->stream.msg);
}
return Qfalse;
} Дословный перевод из оригинальной документации:
What is this?
:)
Ruby Core © 1993–2020 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.