Project

General

Profile

Feature #5937 ยป zlib.c.add_dictionary.patch

drbrain (Eric Hodel), 01/27/2012 08:04 AM

View differences:

ext/zlib/zlib.c (working copy)
56 56

  
57 57
#define sizeof(x) ((int)sizeof(x))
58 58

  
59
static ID id_dictionaries;
60

  
59 61
/*--------- Prototypes --------*/
60 62

  
61 63
static NORETURN(void raise_zlib_error(int, const char*));
......
875 877
	    if (z->stream.avail_in > 0) {
876 878
		zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
877 879
	    }
880
	    if (err == Z_NEED_DICT) {
881
		VALUE self = (VALUE)z->stream.opaque;
882
		VALUE dicts = rb_ivar_get(self, id_dictionaries);
883
		VALUE dict = rb_hash_aref(dicts, rb_uint2inum(z->stream.adler));
884
		if (!NIL_P(dict)) {
885
		    rb_inflate_set_dictionary(self, dict);
886
		    continue;
887
		}
888
	    }
878 889
	    raise_zlib_error(err, z->stream.msg);
879 890
	}
880 891
	if (z->stream.avail_out > 0) {
......
965 976
    obj = Data_Make_Struct(klass, struct zstream,
966 977
			   zstream_mark, zstream_free, z);
967 978
    zstream_init(z, funcs);
979
    z->stream.opaque = (voidpf)obj;
968 980
    return obj;
969 981
}
970 982

  
......
1602 1614
 * dup) itself.
1603 1615
 */
1604 1616

  
1605

  
1606

  
1607 1617
static VALUE
1608 1618
rb_inflate_s_allocate(VALUE klass)
1609 1619
{
1610
    return zstream_inflate_new(klass);
1620
    VALUE inflate = zstream_inflate_new(klass);
1621
    rb_ivar_set(inflate, id_dictionaries, rb_hash_new());
1622
    return inflate;
1611 1623
}
1612 1624

  
1613 1625
/*
......
1737 1749
    }
1738 1750
}
1739 1751

  
1752
/* Document-method: Zlib::Inflate#add_dictionary
1753
 *
1754
 * call-seq: add_dictionary(string)
1755
 *
1756
 * Provide the inflate stream with a dictionary that may be required in the
1757
 * future.  Multiple dictionaries may be provided.  The inflate stream will
1758
 * automatically choose the correct user-provided dictionary based on the
1759
 * stream's required dictionary.
1760
 */
1761
static VALUE
1762
rb_inflate_add_dictionary(VALUE obj, VALUE dictionary) {
1763
    VALUE dictionaries = rb_ivar_get(obj, id_dictionaries);
1764
    VALUE checksum = do_checksum(1, &dictionary, adler32);
1765

  
1766
    rb_hash_aset(dictionaries, checksum, dictionary);
1767

  
1768
    return obj;
1769
}
1770

  
1740 1771
/*
1741 1772
 * Document-method: Zlib::Inflate#inflate
1742 1773
 *
......
4002 4033

  
4003 4034
    mZlib = rb_define_module("Zlib");
4004 4035

  
4036
    id_dictionaries = rb_intern("@dictionaries");
4037

  
4005 4038
    cZError = rb_define_class_under(mZlib, "Error", rb_eStandardError);
4006 4039
    cStreamEnd    = rb_define_class_under(mZlib, "StreamEnd", cZError);
4007 4040
    cNeedDict     = rb_define_class_under(mZlib, "NeedDict", cZError);
......
4070 4103
    rb_define_singleton_method(mZlib, "inflate", rb_inflate_s_inflate, 1);
4071 4104
    rb_define_alloc_func(cInflate, rb_inflate_s_allocate);
4072 4105
    rb_define_method(cInflate, "initialize", rb_inflate_initialize, -1);
4106
    rb_define_method(cInflate, "add_dictionary", rb_inflate_add_dictionary, 1);
4073 4107
    rb_define_method(cInflate, "inflate", rb_inflate_inflate, 1);
4074 4108
    rb_define_method(cInflate, "<<", rb_inflate_addstr, 1);
4075 4109
    rb_define_method(cInflate, "sync", rb_inflate_sync, 1);
test/zlib/test_zlib.rb (working copy)
185 185
      assert_equal("foo", z.finish)
186 186
    end
187 187

  
188
    def test_add_dictionary
189
      dictionary = "foo"
190

  
191
      deflate = Zlib::Deflate.new
192
      deflate.set_dictionary dictionary
193
      compressed = deflate.deflate "foofoofoo", Zlib::FINISH
194
      deflate.close
195

  
196
      out = nil
197
      inflate = Zlib::Inflate.new
198
      inflate.add_dictionary "foo"
199

  
200
      out = inflate.inflate compressed
201

  
202
      assert_equal "foofoofoo", out
203
    end
204

  
188 205
    def test_inflate
189 206
      s = Zlib::Deflate.deflate("foo")
190 207
      z = Zlib::Inflate.new