extlzma 0.4-x86-mingw32

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.
data/ext/filter.c ADDED
@@ -0,0 +1,517 @@
1
+ #include "extlzma.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 *
10
+ setup_lzma_preset(size_t preset)
11
+ {
12
+ lzma_options_lzma *lzma = xcalloc(sizeof(lzma_options_lzma), 1);
13
+ if (lzma_lzma_preset(lzma, preset)) {
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
+ filter->MEMBER = DEFAULT; \
205
+ } else { \
206
+ filter->MEMBER = NUM2UINT(n); \
207
+ } \
208
+ } \
209
+ \
210
+ static VALUE \
211
+ SET(VALUE self, VALUE n) \
212
+ { \
213
+ SET0((lzma_options_lzma *)extlzma_getfilter(self)->options, n); \
214
+ return self; \
215
+ } \
216
+ \
217
+ static VALUE \
218
+ GET(VALUE self) \
219
+ { \
220
+ lzma_options_lzma *p = extlzma_getfilter(self)->options; \
221
+ return UINT2NUM(p->MEMBER); \
222
+ } \
223
+
224
+ DEFINE_ACCESSOR_ENTITY(aux_set_dictsize_0, ext_set_dictsize, ext_get_dictsize, dict_size, LZMA_DICT_SIZE_DEFAULT);
225
+ DEFINE_ACCESSOR_ENTITY(aux_set_lc_0, ext_set_lc, ext_get_lc, lc, LZMA_LC_DEFAULT);
226
+ DEFINE_ACCESSOR_ENTITY(aux_set_lp_0, ext_set_lp, ext_get_lp, lp, LZMA_LP_DEFAULT);
227
+ DEFINE_ACCESSOR_ENTITY(aux_set_pb_0, ext_set_pb, ext_get_pb, pb, LZMA_PB_DEFAULT);
228
+ DEFINE_ACCESSOR_ENTITY(aux_set_mode_0, ext_set_mode, ext_get_mode, mode, LZMA_MODE_NORMAL);
229
+ DEFINE_ACCESSOR_ENTITY(aux_set_nice_0, ext_set_nice, ext_get_nice, nice_len, 64);
230
+ DEFINE_ACCESSOR_ENTITY(aux_set_mf_0, ext_set_mf, ext_get_mf, mf, LZMA_MF_BT4);
231
+ DEFINE_ACCESSOR_ENTITY(aux_set_depth_0, ext_set_depth, ext_get_depth, depth, 0);
232
+
233
+ #undef DEFINE_ACCESSOR_ENTITY
234
+
235
+ static ID ivar_id_predict;
236
+
237
+ static inline void
238
+ aux_set_predict_nil(lzma_options_lzma *filter)
239
+ {
240
+ filter->preset_dict = NULL;
241
+ filter->preset_dict_size = 0;
242
+ }
243
+
244
+ static inline void
245
+ aux_set_predict_string(lzma_options_lzma *filter, VALUE *predict)
246
+ {
247
+ *predict = rb_str_new_frozen(*predict);
248
+ filter->preset_dict = (uint8_t *)(RSTRING_PTR(*predict));
249
+ filter->preset_dict_size = RSTRING_LEN(*predict);
250
+ }
251
+
252
+ static inline void
253
+ aux_set_predict_0(lzma_options_lzma *filter, VALUE predict, VALUE self)
254
+ {
255
+ if (NIL_P(predict)) {
256
+ aux_set_predict_nil(filter);
257
+ } else if (TYPE(predict) == T_STRING) {
258
+ if (RSTRING_LEN(predict) > 0) {
259
+ aux_set_predict_string(filter, &predict);
260
+ } else {
261
+ aux_set_predict_nil(filter);
262
+ }
263
+ } else {
264
+ rb_raise(rb_eTypeError, "%s", "predict is not a String or nil");
265
+ }
266
+
267
+ rb_obj_infect(self, predict);
268
+ rb_ivar_set(self, ivar_id_predict, predict);
269
+ }
270
+
271
+ static VALUE
272
+ ext_set_predict(VALUE self, VALUE predict)
273
+ {
274
+ aux_set_predict_0((lzma_options_lzma *)extlzma_getfilter(self)->options, predict, self);
275
+ return self;
276
+ }
277
+
278
+ static VALUE
279
+ ext_get_predict(VALUE self)
280
+ {
281
+ VALUE predict = rb_attr_get(self, ivar_id_predict);
282
+ if (!NIL_P(predict)) { predict = rb_str_new_shared(predict); }
283
+ return predict;
284
+ }
285
+
286
+ static void *
287
+ setup_lzma(VALUE obj, uint32_t preset,
288
+ VALUE dictsize, VALUE predict, VALUE lc, VALUE lp, VALUE pb,
289
+ VALUE mode, VALUE nice, VALUE mf, VALUE depth)
290
+ {
291
+ lzma_options_lzma lzma = { 0 };
292
+ if (lzma_lzma_preset(&lzma, preset) != 0) {
293
+ rb_raise(extlzma_eBadPreset, "bad preset (0x%08x)", preset);
294
+ }
295
+
296
+ if (RTEST(predict)) { aux_set_predict_0(&lzma, predict, obj); }
297
+
298
+ #define SETVAR(NAME) \
299
+ if (RTEST(NAME)) { aux_set_ ## NAME ## _0(&lzma, NAME); } \
300
+
301
+ SETVAR(dictsize);
302
+ SETVAR(lc);
303
+ SETVAR(lp);
304
+ SETVAR(pb);
305
+ SETVAR(mode);
306
+ SETVAR(nice);
307
+ SETVAR(mf);
308
+ SETVAR(depth);
309
+
310
+ #undef SETVAR
311
+
312
+ {
313
+ lzma_options_lzma *p = ALLOC(lzma_options_lzma);
314
+ memcpy(p, &lzma, sizeof(lzma));
315
+ return (void *)(p);
316
+ }
317
+ }
318
+
319
+ static void
320
+ cleanup_filter(lzma_filter *filter)
321
+ {
322
+ if (filter->options) { xfree(filter->options); }
323
+ xfree(filter);
324
+ }
325
+
326
+
327
+ static uint32_t
328
+ getpreset(VALUE preset)
329
+ {
330
+ if (NIL_P(preset)) {
331
+ return LZMA_PRESET_DEFAULT;
332
+ } else {
333
+ return NUM2UINT(preset);
334
+ }
335
+ }
336
+
337
+ static inline VALUE
338
+ filter_alloc(VALUE klass, lzma_vli id)
339
+ {
340
+ lzma_filter *filter;
341
+ VALUE obj = Data_Make_Struct(klass, lzma_filter, NULL, cleanup_filter, filter);
342
+ memset(filter, 0, sizeof(*filter));
343
+ filter->id = id;
344
+ return obj;
345
+ }
346
+
347
+ static VALUE
348
+ lzma1_alloc(VALUE klass)
349
+ {
350
+ return filter_alloc(klass, LZMA_FILTER_LZMA1);
351
+ }
352
+
353
+ static VALUE
354
+ lzma2_alloc(VALUE klass)
355
+ {
356
+ return filter_alloc(klass, LZMA_FILTER_LZMA2);
357
+ }
358
+
359
+ static VALUE
360
+ delta_alloc(VALUE klass)
361
+ {
362
+ return filter_alloc(cDelta, LZMA_FILTER_DELTA);
363
+ }
364
+
365
+ /*
366
+ * call-seq:
367
+ * initialize(dist = LZMA::DELTA_DIST_MIN)
368
+ *
369
+ * 差分フィルタ設定オブジェクトを返します。
370
+ *
371
+ * distは1要素あたりのバイト長で、1以上255以下を指定できます。
372
+ *
373
+ * NOTE::
374
+ * 使用する場合多くの場合1で十分と思われますが、音楽CDの音声データであれば1サンプル2バイトであるため2が有効でしょう。
375
+ *
376
+ * しかし元のデータによっては圧縮効率を低下させることがあるため、実際に適用するべきかはデータの特性によって検証するのが好ましいです。
377
+ */
378
+ static VALUE
379
+ delta_init(int argc, VALUE argv[], VALUE self)
380
+ {
381
+ lzma_filter *filter = extlzma_getfilter(self);
382
+ lzma_options_delta *delta = ALLOC(lzma_options_delta);
383
+ memset(delta, 0, sizeof(*delta));
384
+
385
+ VALUE preset = Qnil;
386
+ rb_scan_args(argc, argv, "01", &preset);
387
+ delta->type = LZMA_DELTA_TYPE_BYTE;
388
+ delta->dist = NIL_P(preset) ? LZMA_DELTA_DIST_MIN : NUM2UINT(preset);
389
+ filter->options = delta;
390
+ return self;
391
+ }
392
+
393
+ /*
394
+ * call-seq:
395
+ * initialize(preset = LZMA::PRESET_DEFAULT, opts = {}) -> filter
396
+ *
397
+ * LZMA フィルタ設定オブジェクトを初期化します。
398
+ *
399
+ * この段階で各値の確認を行うことはせず、*encoderに渡すときに初めて確認されます。
400
+ *
401
+ * [preset = LZMA::PRESET_DEFAULT]
402
+ * プリセット値 (≒圧縮レベル) を 0-9 の範囲で指定し、任意で LZMA::PRESET_EXTREME を論理和で組み合わせることが出来ます。
403
+ * [opts dictsize]
404
+ * 辞書の大きさをバイト値で指定します。既定値は preset によって変化します。
405
+ * [opts predict: nil]
406
+ * 定義済み辞書を指定します。既定値は nil です。
407
+ * [opts lc: nil]
408
+ * 既定値は preset によって変化します。
409
+ * [opts lp: nil]
410
+ * 既定値は preset によって変化します。
411
+ * [opts pb: nil]
412
+ * 既定値は preset によって変化します。
413
+ * [opts mode: nil]
414
+ * 既定値は preset によって変化します。
415
+ * [opts nice: nil]
416
+ * 既定値は preset によって変化します。
417
+ * [opts mf: nil]
418
+ * 既定値は preset によって変化します。
419
+ * [opts depth: nil]
420
+ * 既定値は preset によって変化します。
421
+ * [RETURN]
422
+ * フィルタオブジェクト
423
+ * [EXCEPTIONS]
424
+ * (NO DOCUMENT)
425
+ */
426
+ static VALUE
427
+ ext_lzma_init(int argc, VALUE argv[], VALUE self)
428
+ {
429
+ VALUE preset = Qnil;
430
+ VALUE opts = Qnil;
431
+ rb_scan_args(argc, argv, "01:", &preset, &opts);
432
+ lzma_filter *filter = extlzma_getfilter(self);
433
+ if (NIL_P(opts)) {
434
+ filter->options = setup_lzma_preset(getpreset(preset));
435
+ } else {
436
+ filter->options = setup_lzma(self, getpreset(preset),
437
+ rb_hash_lookup(opts, ID2SYM(extlzma_id_dictsize)),
438
+ rb_hash_lookup(opts, ID2SYM(extlzma_id_predict)),
439
+ rb_hash_lookup(opts, ID2SYM(extlzma_id_lc)),
440
+ rb_hash_lookup(opts, ID2SYM(extlzma_id_lp)),
441
+ rb_hash_lookup(opts, ID2SYM(extlzma_id_pb)),
442
+ rb_hash_lookup(opts, ID2SYM(extlzma_id_mode)),
443
+ rb_hash_lookup(opts, ID2SYM(extlzma_id_nice)),
444
+ rb_hash_lookup(opts, ID2SYM(extlzma_id_mf)),
445
+ rb_hash_lookup(opts, ID2SYM(extlzma_id_depth)));
446
+ }
447
+ return self;
448
+ }
449
+
450
+ /*
451
+ * Document-class: LZMA::Filter
452
+ *
453
+ * LZMA::Filter クラスは、各圧縮器や伸張器の生成時に用いるフィルタ情報を取り扱います。
454
+ *
455
+ * liblzma で定義されているフィルタはそれぞれ LZMA::Filter::LZMA1 /
456
+ * LZMA::Filter::LZMA2 / LZMA::Filter::Delta として定義されています。
457
+ *
458
+ * これらのクラスについてはそれぞれの文書を見てください。
459
+ */
460
+
461
+ /*
462
+ * Document-class: LZMA::Filter::BasicLZMA
463
+ *
464
+ * LZMA::Filter::LZMA1 と LZMA::Filter::LZMA2 の基本となるクラスです。
465
+ *
466
+ * allocator を持たないため、このクラス自身はインスタンスを作成することが出来ません。
467
+ */
468
+
469
+ /*
470
+ * Document-method: LZMA::Filter::BasicLZMA#dictsize -> integer
471
+ *
472
+ * call-seq:
473
+ * dictsize -> 辞書サイズ (バイト長)
474
+ *
475
+ * 様々なフィルタ値の設定・取り出しを行う
476
+ */
477
+
478
+ void
479
+ extlzma_init_Filter(void)
480
+ {
481
+ ivar_id_predict = rb_intern_const("extlzma.predict");
482
+
483
+ extlzma_cFilter = rb_define_class_under(extlzma_mLZMA, "Filter", rb_cObject);
484
+ rb_undef_alloc_func(extlzma_cFilter);
485
+
486
+ cBasicLZMA = rb_define_class_under(extlzma_cFilter, "BasicLZMA", extlzma_cFilter);
487
+ rb_define_method(cBasicLZMA, "initialize", ext_lzma_init, -1);
488
+
489
+ cLZMA1 = rb_define_class_under(extlzma_cFilter, "LZMA1", cBasicLZMA);
490
+ rb_define_alloc_func(cLZMA1, lzma1_alloc);
491
+
492
+ cLZMA2 = rb_define_class_under(extlzma_cFilter, "LZMA2", cBasicLZMA);
493
+ rb_define_alloc_func(cLZMA2, lzma2_alloc);
494
+
495
+ cDelta = rb_define_class_under(extlzma_cFilter, "Delta", extlzma_cFilter);
496
+ rb_define_alloc_func(cDelta, delta_alloc);
497
+ rb_define_method(cDelta, "initialize", delta_init, -1);
498
+
499
+ rb_define_method(cBasicLZMA, "dictsize", ext_get_dictsize, 0);
500
+ rb_define_method(cBasicLZMA, "dictsize=", ext_set_dictsize, 1);
501
+ rb_define_method(cBasicLZMA, "predict", ext_get_predict, 0);
502
+ rb_define_method(cBasicLZMA, "predict=", ext_set_predict, 1);
503
+ rb_define_method(cBasicLZMA, "lc", ext_get_lc, 0);
504
+ rb_define_method(cBasicLZMA, "lc=", ext_set_lc, 1);
505
+ rb_define_method(cBasicLZMA, "lp", ext_get_lp, 0);
506
+ rb_define_method(cBasicLZMA, "lp=", ext_set_lp, 1);
507
+ rb_define_method(cBasicLZMA, "pb", ext_get_pb, 0);
508
+ rb_define_method(cBasicLZMA, "pb=", ext_set_pb, 1);
509
+ rb_define_method(cBasicLZMA, "mode", ext_get_mode, 0);
510
+ rb_define_method(cBasicLZMA, "mode=", ext_set_mode, 1);
511
+ rb_define_method(cBasicLZMA, "nice", ext_get_nice, 0);
512
+ rb_define_method(cBasicLZMA, "nice=", ext_set_nice, 1);
513
+ rb_define_method(cBasicLZMA, "mf", ext_get_mf, 0);
514
+ rb_define_method(cBasicLZMA, "mf=", ext_set_mf, 1);
515
+ rb_define_method(cBasicLZMA, "depth", ext_get_depth, 0);
516
+ rb_define_method(cBasicLZMA, "depth=", ext_set_depth, 1);
517
+ }