extlzma2 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,530 @@
1
+ #include "extlzma2.h"
2
+
3
+ VALUE extlzma_cFilter;
4
+ static VALUE cBasicLZMA;
5
+ static VALUE cLZMA1;
6
+ static VALUE cLZMA2;
7
+ static VALUE cDelta;
8
+
9
+ static void *setup_lzma_preset(size_t preset)
10
+ {
11
+ lzma_options_lzma *lzma = xcalloc(sizeof(lzma_options_lzma), 1);
12
+ if (lzma_lzma_preset(lzma, preset))
13
+ {
14
+ free(lzma);
15
+ rb_raise(rb_eArgError,
16
+ "wrong preset level (%u for 0..9) or wrong flag bit(s) (0x%08x)",
17
+ (unsigned int)(preset & LZMA_PRESET_LEVEL_MASK),
18
+ (unsigned int)(preset & ~LZMA_PRESET_LEVEL_MASK & ~LZMA_PRESET_EXTREME));
19
+ }
20
+ return (void *)(lzma);
21
+ }
22
+
23
+ /*
24
+ * Document-method: LZMA::Filter::BasicLZMA#dict
25
+ *
26
+ * call-seq:
27
+ * dict -> string or nil
28
+ *
29
+ * 定義済み辞書を取得します。
30
+ *
31
+ * [RETURN] 定義済み辞書が定義されている場合は文字列が返ります。定義されていなければ +nil+ が返ります。
32
+ *
33
+ * エンコード情報は無視されます (常に Encoding::BINARY として扱われます)。呼び出し側で統一しておくべきです。
34
+ *
35
+ * 返される文字列は定義辞書の複成体です。変更しても定義情報には反映されません。+#dict=+ と併せて利用して下さい。
36
+ */
37
+
38
+ /*
39
+ * Document-method: LZMA::Filter::BasicLZMA#dict=
40
+ *
41
+ * call-seq:
42
+ * dict=(dict)
43
+ *
44
+ * 定義済み辞書を定義します。
45
+ *
46
+ * [dict] 定義済み辞書として文字列を与えます。定義を無効にする (定義済み辞書を利用しない) には、+nil+ を与えます。
47
+ *
48
+ * エンコード情報は無視されます (常に Encoding::BINARY として扱われます)。呼び出し側で統一しておくべきです。
49
+ *
50
+ * 与えた文字列は内部で複写され、元の文字列とは独立します。文字列の変更を反映したい場合はその都度 +#dict=+ を呼ぶ必要があります。
51
+ *
52
+ * [RETURN] 自身 (self) を返します。
53
+ */
54
+
55
+ /*
56
+ * Document-method: LZMA::Filter::BasicLZMA#dictsize
57
+ *
58
+ * call-seq:
59
+ * dictsize -> integer
60
+ *
61
+ * 辞書の大きさをバイト値として取得します。
62
+ */
63
+
64
+ /*
65
+ * Document-method: LZMA::Filter::BasicLZMA#dictsize=
66
+ *
67
+ * call-seq:
68
+ * dictsize=(size) -> self
69
+ *
70
+ * 辞書の大きさをバイト値として設定します。
71
+ */
72
+
73
+ /*
74
+ * Document-method: LZMA::Filter::BasicLZMA#lc
75
+ *
76
+ * call-seq:
77
+ * lc -> integer
78
+ *
79
+ * lc 値を取得します。
80
+ */
81
+
82
+ /*
83
+ * Document-method: LZMA::Filter::BasicLZMA#lc=
84
+ *
85
+ * call-seq:
86
+ * lc=(value) -> self
87
+ *
88
+ * lc 値を設定します。
89
+ */
90
+
91
+ /*
92
+ * Document-method: LZMA::Filter::BasicLZMA#lp
93
+ *
94
+ * call-seq:
95
+ * lp -> integer
96
+ *
97
+ * lp 値を取得します。
98
+ */
99
+
100
+ /*
101
+ * Document-method: LZMA::Filter::BasicLZMA#lp=
102
+ *
103
+ * call-seq:
104
+ * lp=(value) -> self
105
+ *
106
+ * lp 値を設定します。
107
+ */
108
+
109
+ /*
110
+ * Document-method: LZMA::Filter::BasicLZMA#pb
111
+ *
112
+ * call-seq:
113
+ * pb -> integer
114
+ *
115
+ * pb 値を取得します。
116
+ */
117
+
118
+ /*
119
+ * Document-method: LZMA::Filter::BasicLZMA#pb=
120
+ *
121
+ * call-seq:
122
+ * pb=(value) -> self
123
+ *
124
+ * pb 値を設定します。
125
+ */
126
+
127
+ /*
128
+ * Document-method: LZMA::Filter::BasicLZMA#mode
129
+ *
130
+ * call-seq:
131
+ * mode -> integer
132
+ *
133
+ * mode 値を取得します。
134
+ */
135
+
136
+ /*
137
+ * Document-method: LZMA::Filter::BasicLZMA#mode=
138
+ *
139
+ * call-seq:
140
+ * mode=(value) -> self
141
+ *
142
+ * mode 値を設定します。
143
+ */
144
+
145
+ /*
146
+ * Document-method: LZMA::Filter::BasicLZMA#nice
147
+ *
148
+ * call-seq:
149
+ * nice -> integer
150
+ *
151
+ * nice 値を取得します。
152
+ */
153
+
154
+ /*
155
+ * Document-method: LZMA::Filter::BasicLZMA#nice=
156
+ *
157
+ * call-seq:
158
+ * nice=(value) -> self
159
+ *
160
+ * nice 値を設定します。
161
+ */
162
+
163
+ /*
164
+ * Document-method: LZMA::Filter::BasicLZMA#mf
165
+ *
166
+ * call-seq:
167
+ * mf -> integer
168
+ *
169
+ * mf 値を取得します。
170
+ */
171
+
172
+ /*
173
+ * Document-method: LZMA::Filter::BasicLZMA#mf=
174
+ *
175
+ * call-seq:
176
+ * mf=(value) -> self
177
+ *
178
+ * mf 値を設定します。
179
+ */
180
+
181
+ /*
182
+ * Document-method: LZMA::Filter::BasicLZMA#depth
183
+ *
184
+ * call-seq:
185
+ * depth -> integer
186
+ *
187
+ * depth 値を取得します。
188
+ */
189
+
190
+ /*
191
+ * Document-method: LZMA::Filter::BasicLZMA#depth=
192
+ *
193
+ * call-seq:
194
+ * depth=(value) -> self
195
+ *
196
+ * depth 値を設定します。
197
+ */
198
+
199
+ #define DEFINE_ACCESSOR_ENTITY(SET0, SET, GET, MEMBER, DEFAULT) \
200
+ static inline void \
201
+ SET0(lzma_options_lzma *filter, VALUE n) \
202
+ { \
203
+ if (NIL_P(n)) \
204
+ { \
205
+ filter->MEMBER = DEFAULT; \
206
+ } \
207
+ else \
208
+ { \
209
+ filter->MEMBER = NUM2UINT(n); \
210
+ } \
211
+ } \
212
+ \
213
+ static VALUE \
214
+ SET(VALUE self, VALUE n) \
215
+ { \
216
+ SET0((lzma_options_lzma *)extlzma_getfilter(self)->options, n); \
217
+ return self; \
218
+ } \
219
+ \
220
+ static VALUE \
221
+ GET(VALUE self) \
222
+ { \
223
+ lzma_options_lzma *p = extlzma_getfilter(self)->options; \
224
+ return UINT2NUM(p->MEMBER); \
225
+ }
226
+
227
+ DEFINE_ACCESSOR_ENTITY(aux_set_dictsize_0, ext_set_dictsize, ext_get_dictsize, dict_size, LZMA_DICT_SIZE_DEFAULT);
228
+ DEFINE_ACCESSOR_ENTITY(aux_set_lc_0, ext_set_lc, ext_get_lc, lc, LZMA_LC_DEFAULT);
229
+ DEFINE_ACCESSOR_ENTITY(aux_set_lp_0, ext_set_lp, ext_get_lp, lp, LZMA_LP_DEFAULT);
230
+ DEFINE_ACCESSOR_ENTITY(aux_set_pb_0, ext_set_pb, ext_get_pb, pb, LZMA_PB_DEFAULT);
231
+ DEFINE_ACCESSOR_ENTITY(aux_set_mode_0, ext_set_mode, ext_get_mode, mode, LZMA_MODE_NORMAL);
232
+ DEFINE_ACCESSOR_ENTITY(aux_set_nice_0, ext_set_nice, ext_get_nice, nice_len, 64);
233
+ DEFINE_ACCESSOR_ENTITY(aux_set_mf_0, ext_set_mf, ext_get_mf, mf, LZMA_MF_BT4);
234
+ DEFINE_ACCESSOR_ENTITY(aux_set_depth_0, ext_set_depth, ext_get_depth, depth, 0);
235
+
236
+ #undef DEFINE_ACCESSOR_ENTITY
237
+
238
+ static ID ivar_id_predict;
239
+
240
+ static inline void aux_set_predict_nil(lzma_options_lzma *filter)
241
+ {
242
+ filter->preset_dict = NULL;
243
+ filter->preset_dict_size = 0;
244
+ }
245
+
246
+ static inline void aux_set_predict_string(lzma_options_lzma *filter, VALUE *predict)
247
+ {
248
+ *predict = rb_str_new_frozen(*predict);
249
+ filter->preset_dict = (uint8_t *)(RSTRING_PTR(*predict));
250
+ filter->preset_dict_size = RSTRING_LENINT(*predict);
251
+ }
252
+
253
+ static inline void aux_set_predict_0(lzma_options_lzma *filter, VALUE predict, VALUE self)
254
+ {
255
+ if (NIL_P(predict))
256
+ {
257
+ aux_set_predict_nil(filter);
258
+ }
259
+ else if (TYPE(predict) == T_STRING)
260
+ {
261
+ if (RSTRING_LEN(predict) > 0)
262
+ {
263
+ aux_set_predict_string(filter, &predict);
264
+ }
265
+ else
266
+ {
267
+ aux_set_predict_nil(filter);
268
+ }
269
+ }
270
+ else
271
+ {
272
+ rb_raise(rb_eTypeError, "%s", "predict is not a String or nil");
273
+ }
274
+
275
+ rb_ivar_set(self, ivar_id_predict, predict);
276
+ }
277
+
278
+ static VALUE ext_set_predict(VALUE self, VALUE predict)
279
+ {
280
+ aux_set_predict_0((lzma_options_lzma *)extlzma_getfilter(self)->options, predict, self);
281
+ return self;
282
+ }
283
+
284
+ static VALUE ext_get_predict(VALUE self)
285
+ {
286
+ VALUE predict = rb_attr_get(self, ivar_id_predict);
287
+ if (!NIL_P(predict))
288
+ {
289
+ predict = rb_str_new_shared(predict);
290
+ }
291
+ return predict;
292
+ }
293
+
294
+ static void *setup_lzma(VALUE obj, uint32_t preset,
295
+ VALUE dictsize, VALUE predict, VALUE lc, VALUE lp, VALUE pb,
296
+ VALUE mode, VALUE nice, VALUE mf, VALUE depth)
297
+ {
298
+ lzma_options_lzma lzma = {0};
299
+ if (lzma_lzma_preset(&lzma, preset) != 0)
300
+ {
301
+ rb_raise(extlzma_eBadPreset, "bad preset (0x%08x)", preset);
302
+ }
303
+
304
+ if (RTEST(predict))
305
+ {
306
+ aux_set_predict_0(&lzma, predict, obj);
307
+ }
308
+
309
+ #define SETVAR(NAME) \
310
+ if (RTEST(NAME)) \
311
+ { \
312
+ aux_set_##NAME##_0(&lzma, NAME); \
313
+ }
314
+
315
+ SETVAR(dictsize);
316
+ SETVAR(lc);
317
+ SETVAR(lp);
318
+ SETVAR(pb);
319
+ SETVAR(mode);
320
+ SETVAR(nice);
321
+ SETVAR(mf);
322
+ SETVAR(depth);
323
+
324
+ #undef SETVAR
325
+
326
+ {
327
+ lzma_options_lzma *p = ALLOC(lzma_options_lzma);
328
+ memcpy(p, &lzma, sizeof(lzma));
329
+ return (void *)(p);
330
+ }
331
+ }
332
+
333
+ static void cleanup_filter(lzma_filter *filter)
334
+ {
335
+ if (filter->options)
336
+ {
337
+ xfree(filter->options);
338
+ }
339
+ xfree(filter);
340
+ }
341
+
342
+ static uint32_t getpreset(VALUE preset)
343
+ {
344
+ if (NIL_P(preset))
345
+ {
346
+ return LZMA_PRESET_DEFAULT;
347
+ }
348
+ else
349
+ {
350
+ return NUM2UINT(preset);
351
+ }
352
+ }
353
+
354
+ static inline VALUE filter_alloc(VALUE klass, lzma_vli id)
355
+ {
356
+ lzma_filter *filter;
357
+ VALUE obj = Data_Make_Struct(klass, lzma_filter, NULL, cleanup_filter, filter);
358
+ memset(filter, 0, sizeof(*filter));
359
+ filter->id = id;
360
+ return obj;
361
+ }
362
+
363
+ static VALUE lzma1_alloc(VALUE klass)
364
+ {
365
+ return filter_alloc(klass, LZMA_FILTER_LZMA1);
366
+ }
367
+
368
+ static VALUE lzma2_alloc(VALUE klass)
369
+ {
370
+ return filter_alloc(klass, LZMA_FILTER_LZMA2);
371
+ }
372
+
373
+ static VALUE delta_alloc(VALUE klass)
374
+ {
375
+ return filter_alloc(cDelta, LZMA_FILTER_DELTA);
376
+ }
377
+
378
+ /*
379
+ * call-seq:
380
+ * initialize(dist = LZMA::DELTA_DIST_MIN)
381
+ *
382
+ * 差分フィルタ設定オブジェクトを返します。
383
+ *
384
+ * distは1要素あたりのバイト長で、1以上255以下を指定できます。
385
+ *
386
+ * NOTE::
387
+ * 使用する場合多くの場合1で十分と思われますが、音楽CDの音声データであれば1サンプル2バイトであるため2が有効でしょう。
388
+ *
389
+ * しかし元のデータによっては圧縮効率を低下させることがあるため、実際に適用するべきかはデータの特性によって検証するのが好ましいです。
390
+ */
391
+ static VALUE delta_init(int argc, VALUE argv[], VALUE self)
392
+ {
393
+ lzma_filter *filter = extlzma_getfilter(self);
394
+ lzma_options_delta *delta = ALLOC(lzma_options_delta);
395
+ memset(delta, 0, sizeof(*delta));
396
+
397
+ VALUE preset = Qnil;
398
+ rb_scan_args(argc, argv, "01", &preset);
399
+ delta->type = LZMA_DELTA_TYPE_BYTE;
400
+ delta->dist = NIL_P(preset) ? LZMA_DELTA_DIST_MIN : NUM2UINT(preset);
401
+ filter->options = delta;
402
+ return self;
403
+ }
404
+
405
+ /*
406
+ * call-seq:
407
+ * initialize(preset = LZMA::PRESET_DEFAULT, opts = {}) -> filter
408
+ *
409
+ * LZMA フィルタ設定オブジェクトを初期化します。
410
+ *
411
+ * この段階で各値の確認を行うことはせず、*encoderに渡すときに初めて確認されます。
412
+ *
413
+ * [preset = LZMA::PRESET_DEFAULT]
414
+ * プリセット値 (≒圧縮レベル) を 0-9 の範囲で指定し、任意で LZMA::PRESET_EXTREME を論理和で組み合わせることが出来ます。
415
+ * [opts dictsize]
416
+ * 辞書の大きさをバイト値で指定します。既定値は preset によって変化します。
417
+ * [opts predict: nil]
418
+ * 定義済み辞書を指定します。既定値は nil です。
419
+ * [opts lc: nil]
420
+ * 既定値は preset によって変化します。
421
+ * [opts lp: nil]
422
+ * 既定値は preset によって変化します。
423
+ * [opts pb: nil]
424
+ * 既定値は preset によって変化します。
425
+ * [opts mode: nil]
426
+ * 既定値は preset によって変化します。
427
+ * [opts nice: nil]
428
+ * 既定値は preset によって変化します。
429
+ * [opts mf: nil]
430
+ * 既定値は preset によって変化します。
431
+ * [opts depth: nil]
432
+ * 既定値は preset によって変化します。
433
+ * [RETURN]
434
+ * フィルタオブジェクト
435
+ * [EXCEPTIONS]
436
+ * (NO DOCUMENT)
437
+ */
438
+ static VALUE ext_lzma_init(int argc, VALUE argv[], VALUE self)
439
+ {
440
+ VALUE preset = Qnil;
441
+ VALUE opts = Qnil;
442
+ rb_scan_args(argc, argv, "01:", &preset, &opts);
443
+ lzma_filter *filter = extlzma_getfilter(self);
444
+ if (NIL_P(opts))
445
+ {
446
+ filter->options = setup_lzma_preset(getpreset(preset));
447
+ }
448
+ else
449
+ {
450
+ filter->options = setup_lzma(self, getpreset(preset),
451
+ rb_hash_lookup(opts, ID2SYM(extlzma_id_dictsize)),
452
+ rb_hash_lookup(opts, ID2SYM(extlzma_id_predict)),
453
+ rb_hash_lookup(opts, ID2SYM(extlzma_id_lc)),
454
+ rb_hash_lookup(opts, ID2SYM(extlzma_id_lp)),
455
+ rb_hash_lookup(opts, ID2SYM(extlzma_id_pb)),
456
+ rb_hash_lookup(opts, ID2SYM(extlzma_id_mode)),
457
+ rb_hash_lookup(opts, ID2SYM(extlzma_id_nice)),
458
+ rb_hash_lookup(opts, ID2SYM(extlzma_id_mf)),
459
+ rb_hash_lookup(opts, ID2SYM(extlzma_id_depth)));
460
+ }
461
+ return self;
462
+ }
463
+
464
+ /*
465
+ * Document-class: LZMA::Filter
466
+ *
467
+ * LZMA::Filter クラスは、各圧縮器や伸張器の生成時に用いるフィルタ情報を取り扱います。
468
+ *
469
+ * liblzma で定義されているフィルタはそれぞれ LZMA::Filter::LZMA1 /
470
+ * LZMA::Filter::LZMA2 / LZMA::Filter::Delta として定義されています。
471
+ *
472
+ * これらのクラスについてはそれぞれの文書を見てください。
473
+ */
474
+
475
+ /*
476
+ * Document-class: LZMA::Filter::BasicLZMA
477
+ *
478
+ * LZMA::Filter::LZMA1 と LZMA::Filter::LZMA2 の基本となるクラスです。
479
+ *
480
+ * allocator を持たないため、このクラス自身はインスタンスを作成することが出来ません。
481
+ */
482
+
483
+ /*
484
+ * Document-method: LZMA::Filter::BasicLZMA#dictsize -> integer
485
+ *
486
+ * call-seq:
487
+ * dictsize -> 辞書サイズ (バイト長)
488
+ *
489
+ * 様々なフィルタ値の設定・取り出しを行う
490
+ */
491
+
492
+ void extlzma_init_Filter(void)
493
+ {
494
+ ivar_id_predict = rb_intern_const("extlzma.predict");
495
+
496
+ extlzma_cFilter = rb_define_class_under(extlzma_mLZMA, "Filter", rb_cObject);
497
+ rb_undef_alloc_func(extlzma_cFilter);
498
+
499
+ cBasicLZMA = rb_define_class_under(extlzma_cFilter, "BasicLZMA", extlzma_cFilter);
500
+ rb_define_method(cBasicLZMA, "initialize", ext_lzma_init, -1);
501
+
502
+ cLZMA1 = rb_define_class_under(extlzma_cFilter, "LZMA1", cBasicLZMA);
503
+ rb_define_alloc_func(cLZMA1, lzma1_alloc);
504
+
505
+ cLZMA2 = rb_define_class_under(extlzma_cFilter, "LZMA2", cBasicLZMA);
506
+ rb_define_alloc_func(cLZMA2, lzma2_alloc);
507
+
508
+ cDelta = rb_define_class_under(extlzma_cFilter, "Delta", extlzma_cFilter);
509
+ rb_define_alloc_func(cDelta, delta_alloc);
510
+ rb_define_method(cDelta, "initialize", delta_init, -1);
511
+
512
+ rb_define_method(cBasicLZMA, "dictsize", ext_get_dictsize, 0);
513
+ rb_define_method(cBasicLZMA, "dictsize=", ext_set_dictsize, 1);
514
+ rb_define_method(cBasicLZMA, "predict", ext_get_predict, 0);
515
+ rb_define_method(cBasicLZMA, "predict=", ext_set_predict, 1);
516
+ rb_define_method(cBasicLZMA, "lc", ext_get_lc, 0);
517
+ rb_define_method(cBasicLZMA, "lc=", ext_set_lc, 1);
518
+ rb_define_method(cBasicLZMA, "lp", ext_get_lp, 0);
519
+ rb_define_method(cBasicLZMA, "lp=", ext_set_lp, 1);
520
+ rb_define_method(cBasicLZMA, "pb", ext_get_pb, 0);
521
+ rb_define_method(cBasicLZMA, "pb=", ext_set_pb, 1);
522
+ rb_define_method(cBasicLZMA, "mode", ext_get_mode, 0);
523
+ rb_define_method(cBasicLZMA, "mode=", ext_set_mode, 1);
524
+ rb_define_method(cBasicLZMA, "nice", ext_get_nice, 0);
525
+ rb_define_method(cBasicLZMA, "nice=", ext_set_nice, 1);
526
+ rb_define_method(cBasicLZMA, "mf", ext_get_mf, 0);
527
+ rb_define_method(cBasicLZMA, "mf=", ext_set_mf, 1);
528
+ rb_define_method(cBasicLZMA, "depth", ext_get_depth, 0);
529
+ rb_define_method(cBasicLZMA, "depth=", ext_set_depth, 1);
530
+ }
@@ -0,0 +1,66 @@
1
+ #include "extlzma2.h"
2
+
3
+ static VALUE cIndex;
4
+ static VALUE cIEncoder;
5
+ static VALUE cIDecoder;
6
+
7
+ static void ext_index_free(lzma_index *index)
8
+ {
9
+ if (index)
10
+ {
11
+ lzma_index_end(index, NULL);
12
+ }
13
+ }
14
+
15
+ static VALUE ext_index_alloc(VALUE klass)
16
+ {
17
+ lzma_index *index = lzma_index_init(NULL);
18
+ if (!index)
19
+ {
20
+ rb_raise(rb_eNoMemError, "failed allocation for lzma index structure");
21
+ }
22
+ return Data_Wrap_Struct(klass, NULL, ext_index_free, index);
23
+ }
24
+
25
+ static lzma_index *ext_index_ref(VALUE index)
26
+ {
27
+ return getref(index);
28
+ }
29
+
30
+ static VALUE iencoder_init(int argc, VALUE argv[], VALUE idx)
31
+ {
32
+ // RDATA_PTR(idx);
33
+
34
+ rb_raise(rb_eNotImpError, "%s", "IMPLEMENT ME!");
35
+ }
36
+
37
+ static VALUE idecoder_init(int argc, VALUE argv[], VALUE idx)
38
+ {
39
+ rb_raise(rb_eNotImpError, "%s", "IMPLEMENT ME!");
40
+ }
41
+
42
+ static VALUE ext_index_memused(VALUE index)
43
+ {
44
+ return ULL2NUM(lzma_index_memused(ext_index_ref(index)));
45
+ }
46
+
47
+ static VALUE ext_index_s_memusage(VALUE index, VALUE streams, VALUE blocks)
48
+ {
49
+ return ULL2NUM(lzma_index_memusage(NUM2ULL(streams), NUM2ULL(blocks)));
50
+ }
51
+
52
+ void extlzma_init_Index(void)
53
+ {
54
+ cIndex = rb_define_class_under(extlzma_mLZMA, "Index", rb_cObject);
55
+ rb_undef_alloc_func(cIndex);
56
+ rb_define_singleton_method(cIndex, "memusage", RUBY_METHOD_FUNC(ext_index_s_memusage), 2);
57
+ rb_define_method(cIndex, "memused", RUBY_METHOD_FUNC(ext_index_memused), 0);
58
+
59
+ cIEncoder = rb_define_class_under(cIndex, "Encoder", cIndex);
60
+ rb_define_alloc_func(cIEncoder, ext_index_alloc);
61
+ rb_define_method(cIEncoder, "initialize", RUBY_METHOD_FUNC(iencoder_init), -1);
62
+
63
+ cIDecoder = rb_define_class_under(cIndex, "Decoder", cIndex);
64
+ rb_define_alloc_func(cIDecoder, ext_index_alloc);
65
+ rb_define_method(cIDecoder, "initialize", RUBY_METHOD_FUNC(idecoder_init), -1);
66
+ }