extlzma2 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ }