72 |
72 |
|
73 |
73 |
struct zstream;
|
74 |
74 |
struct zstream_funcs;
|
|
75 |
struct zstream_run_args;
|
75 |
76 |
static void zstream_init(struct zstream*, const struct zstream_funcs*);
|
76 |
77 |
static void zstream_expand_buffer(struct zstream*);
|
77 |
78 |
static void zstream_expand_buffer_into(struct zstream*, unsigned long);
|
... | ... | |
564 |
565 |
inflateReset, inflateEnd, inflate,
|
565 |
566 |
};
|
566 |
567 |
|
|
568 |
struct zstream_run_args {
|
|
569 |
struct zstream * z;
|
|
570 |
int flush;
|
|
571 |
int interrupt;
|
|
572 |
};
|
567 |
573 |
|
568 |
574 |
static voidpf
|
569 |
575 |
zlib_mem_alloc(voidpf opaque, uInt items, uInt size)
|
... | ... | |
655 |
661 |
}
|
656 |
662 |
}
|
657 |
663 |
|
|
664 |
static int
|
|
665 |
zstream_expand_buffer_without_gvl(struct zstream *z)
|
|
666 |
{
|
|
667 |
char * new_str;
|
|
668 |
long inc, len;
|
|
669 |
|
|
670 |
if (RSTRING_LEN(z->buf) - z->buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
|
|
671 |
z->stream.avail_out = ZSTREAM_AVAIL_OUT_STEP_MAX;
|
|
672 |
}
|
|
673 |
else {
|
|
674 |
inc = z->buf_filled / 2;
|
|
675 |
if (inc < ZSTREAM_AVAIL_OUT_STEP_MIN) {
|
|
676 |
inc = ZSTREAM_AVAIL_OUT_STEP_MIN;
|
|
677 |
}
|
|
678 |
|
|
679 |
len = z->buf_filled + inc;
|
|
680 |
|
|
681 |
new_str = realloc(RSTRING(z->buf)->as.heap.ptr, len + 1);
|
|
682 |
|
|
683 |
if (!new_str)
|
|
684 |
return 0;
|
|
685 |
|
|
686 |
/* from rb_str_resize */
|
|
687 |
RSTRING(z->buf)->as.heap.ptr = new_str;
|
|
688 |
RSTRING(z->buf)->as.heap.ptr[len] = '\0'; /* sentinel */
|
|
689 |
RSTRING(z->buf)->as.heap.len =
|
|
690 |
RSTRING(z->buf)->as.heap.aux.capa = len;
|
|
691 |
|
|
692 |
z->stream.avail_out = (inc < ZSTREAM_AVAIL_OUT_STEP_MAX) ?
|
|
693 |
(int)inc : ZSTREAM_AVAIL_OUT_STEP_MAX;
|
|
694 |
}
|
|
695 |
z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
|
|
696 |
|
|
697 |
return 1;
|
|
698 |
}
|
|
699 |
|
658 |
700 |
static void
|
659 |
701 |
zstream_append_buffer(struct zstream *z, const Bytef *src, long len)
|
660 |
702 |
{
|
... | ... | |
871 |
913 |
return Qnil;
|
872 |
914 |
}
|
873 |
915 |
|
|
916 |
static VALUE
|
|
917 |
zstream_run_func(void *ptr) {
|
|
918 |
struct zstream_run_args *args = (struct zstream_run_args *)ptr;
|
|
919 |
int err, flush = args->flush;
|
|
920 |
struct zstream *z = args->z;
|
|
921 |
uInt n;
|
|
922 |
|
|
923 |
while (!args->interrupt) {
|
|
924 |
n = z->stream.avail_out;
|
|
925 |
err = z->func->run(&z->stream, flush);
|
|
926 |
z->buf_filled += n - z->stream.avail_out;
|
|
927 |
|
|
928 |
if (err == Z_STREAM_END) {
|
|
929 |
z->flags &= ~ZSTREAM_FLAG_IN_STREAM;
|
|
930 |
z->flags |= ZSTREAM_FLAG_FINISHED;
|
|
931 |
break;
|
|
932 |
}
|
|
933 |
|
|
934 |
if (err != Z_OK)
|
|
935 |
break;
|
|
936 |
|
|
937 |
if (z->stream.avail_out > 0) {
|
|
938 |
z->flags |= ZSTREAM_FLAG_IN_STREAM;
|
|
939 |
break;
|
|
940 |
}
|
|
941 |
|
|
942 |
if (!zstream_expand_buffer_without_gvl(z)) {
|
|
943 |
err = Z_MEM_ERROR; /* realloc failed */
|
|
944 |
break;
|
|
945 |
}
|
|
946 |
}
|
|
947 |
|
|
948 |
return (VALUE)err;
|
|
949 |
}
|
|
950 |
|
|
951 |
/*
|
|
952 |
* There is no safe way to interrupt z->run->func().
|
|
953 |
*/
|
|
954 |
static void
|
|
955 |
zstream_unblock_func(void *ptr) {
|
|
956 |
struct zstream_run_args *args = (struct zstream_run_args *)ptr;
|
|
957 |
|
|
958 |
args->interrupt = 1;
|
|
959 |
}
|
|
960 |
|
874 |
961 |
static void
|
875 |
962 |
zstream_run(struct zstream *z, Bytef *src, long len, int flush)
|
876 |
963 |
{
|
877 |
|
uInt n;
|
|
964 |
struct zstream_run_args args;
|
878 |
965 |
int err;
|
879 |
966 |
volatile VALUE guard = Qnil;
|
880 |
967 |
|
|
968 |
args.z = z;
|
|
969 |
args.flush = flush;
|
|
970 |
args.interrupt = 0;
|
|
971 |
|
881 |
972 |
if (NIL_P(z->input) && len == 0) {
|
882 |
973 |
z->stream.next_in = (Bytef*)"";
|
883 |
974 |
z->stream.avail_in = 0;
|
... | ... | |
896 |
987 |
zstream_expand_buffer(z);
|
897 |
988 |
}
|
898 |
989 |
|
899 |
|
for (;;) {
|
900 |
|
/* VC allocates err and guard to same address. accessing err and guard
|
901 |
|
in same scope prevents it. */
|
902 |
|
RB_GC_GUARD(guard);
|
903 |
|
n = z->stream.avail_out;
|
904 |
|
err = z->func->run(&z->stream, flush);
|
905 |
|
z->buf_filled += n - z->stream.avail_out;
|
906 |
|
rb_thread_schedule();
|
|
990 |
loop:
|
|
991 |
err = (int)rb_thread_blocking_region(
|
|
992 |
zstream_run_func, (void *)&args,
|
|
993 |
zstream_unblock_func, (void *)&args);
|
|
994 |
|
|
995 |
if (flush != Z_FINISH && err == Z_BUF_ERROR
|
|
996 |
&& z->stream.avail_out > 0) {
|
|
997 |
z->flags |= ZSTREAM_FLAG_IN_STREAM;
|
|
998 |
}
|
907 |
999 |
|
908 |
|
if (err == Z_STREAM_END) {
|
909 |
|
z->flags &= ~ZSTREAM_FLAG_IN_STREAM;
|
910 |
|
z->flags |= ZSTREAM_FLAG_FINISHED;
|
911 |
|
break;
|
|
1000 |
zstream_reset_input(z);
|
|
1001 |
|
|
1002 |
if (err != Z_OK && err != Z_STREAM_END) {
|
|
1003 |
if (z->stream.avail_in > 0) {
|
|
1004 |
zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
|
912 |
1005 |
}
|
913 |
|
if (err != Z_OK) {
|
914 |
|
if (flush != Z_FINISH && err == Z_BUF_ERROR
|
915 |
|
&& z->stream.avail_out > 0) {
|
916 |
|
z->flags |= ZSTREAM_FLAG_IN_STREAM;
|
917 |
|
break;
|
|
1006 |
if (err == Z_NEED_DICT) {
|
|
1007 |
VALUE self = (VALUE)z->stream.opaque;
|
|
1008 |
VALUE dicts = rb_ivar_get(self, id_dictionaries);
|
|
1009 |
VALUE dict = rb_hash_aref(dicts, rb_uint2inum(z->stream.adler));
|
|
1010 |
if (!NIL_P(dict)) {
|
|
1011 |
rb_inflate_set_dictionary(self, dict);
|
|
1012 |
goto loop;
|
918 |
1013 |
}
|
919 |
|
zstream_reset_input(z);
|
920 |
|
if (z->stream.avail_in > 0) {
|
921 |
|
zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
|
922 |
|
}
|
923 |
|
if (err == Z_NEED_DICT) {
|
924 |
|
VALUE self = (VALUE)z->stream.opaque;
|
925 |
|
VALUE dicts = rb_ivar_get(self, id_dictionaries);
|
926 |
|
VALUE dict = rb_hash_aref(dicts, rb_uint2inum(z->stream.adler));
|
927 |
|
if (!NIL_P(dict)) {
|
928 |
|
rb_inflate_set_dictionary(self, dict);
|
929 |
|
continue;
|
930 |
|
}
|
931 |
|
}
|
932 |
|
raise_zlib_error(err, z->stream.msg);
|
933 |
|
}
|
934 |
|
if (z->stream.avail_out > 0) {
|
935 |
|
z->flags |= ZSTREAM_FLAG_IN_STREAM;
|
936 |
|
break;
|
937 |
1014 |
}
|
938 |
|
zstream_expand_buffer(z);
|
|
1015 |
raise_zlib_error(err, z->stream.msg);
|
939 |
1016 |
}
|
940 |
1017 |
|
941 |
|
zstream_reset_input(z);
|
942 |
1018 |
if (z->stream.avail_in > 0) {
|
943 |
1019 |
zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
|
944 |
1020 |
guard = Qnil; /* prevent tail call to make guard effective */
|