liblzma 0.2

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,43 @@
1
+ # encoding:utf-8
2
+
3
+ = liblzma for Ruby
4
+
5
+ - AUTHOR : dearblue
6
+ - MAIL : dearblue@users.sourceforge.jp
7
+ - LICENSE : 2-clause BSD License (二条項BSDライセンス)
8
+ - PROJECTPAGE : http://sourceforge.jp/projects/rutsubo/
9
+
10
+ This document is written in Japanese.
11
+
12
+
13
+ == はじめに
14
+
15
+ xzユーティリティに含まれるliblzmaのRubyバインディングです。
16
+
17
+ gemパッケージになっており、『gem install liblzma-0.2.gem』でビルド、インストールが完了します。
18
+
19
+ MinGW32およびFreeBSD 9.0R i386で動作確認を行っています。
20
+
21
+ MinGW32向けにはバイナリパッケージも用意してあります (もしかしたらruby-mswin32でも動作するかもしれません)。
22
+
23
+ FreeBSD 9.0R i386 上では標準コンパイラであるGCCのほかにllvm clangでもビルド可能なことを確認してあります。
24
+
25
+
26
+ == 利用できる主な機能
27
+
28
+ ※カッコ内は、本来のliblzmaが提供する関数を示す
29
+
30
+ * LZMA::Stream::Encoder/Decoder (lzma_stream_encoder / lzma_stream_decoder)
31
+ * LZMA::Stream::RawEncoder/RawDecoder (lzma_raw_encoder / lzma_raw_decoder)
32
+ * LZMA::Utils.crc32/crc64 (lzma_crc32 / lzma_crc64)
33
+ * LZMA::Filter::LZMA1/LZMA2/Delta
34
+
35
+
36
+ == 実際に利用するには
37
+
38
+ まともな文書化が出来ていないため、gemパッケージ内の『samples』ディレクトリに含まれる各サンプルを頼りにして下さい。
39
+
40
+
41
+ == ライセンスについて
42
+
43
+ liblzma for Ruby は、二条項BSDライセンスの下で利用できます。
@@ -0,0 +1,11 @@
1
+ require "mkmf"
2
+
3
+ have_header "lzma.h" or raise "need lzma.h"
4
+ have_library "lzma" or raise "need liblzma.a"
5
+ create_makefile "liblzma"
6
+
7
+ # Makefile から、『-L.』を取り除く
8
+ # (本来のliblzma.aではなく、これから作成するliblzma.soへの結合を抑止するため)
9
+ mf = File.read("Makefile", mode: "r:binary")
10
+ mf.gsub!(/(?<=\s)-L\.(?=\s|$)/, " ")
11
+ File.write("Makefile", mf, mode: "wb")
@@ -0,0 +1,1027 @@
1
+ /*
2
+ * liblzma.c -
3
+ * Author:: dearblue <dearblue@sourceforge.jp>
4
+ * Copyright:: Copyright (c) 2010 dearblue
5
+ * License:: Distributed under the 2-clause BSD License
6
+ */
7
+
8
+ #include <ruby.h>
9
+ #include <ruby/intern.h>
10
+ #include <lzma.h>
11
+
12
+
13
+ static VALUE mLZMA;
14
+
15
+
16
+ static VALUE symDICTSIZE;
17
+ static VALUE symPRESETDICT;
18
+ static VALUE symLC;
19
+ static VALUE symLP;
20
+ static VALUE symPB;
21
+ static VALUE symMODE;
22
+ static VALUE symNICE;
23
+ static VALUE symMF;
24
+ static VALUE symDEPTH;
25
+ static VALUE symCHECK;
26
+
27
+
28
+ static inline int
29
+ lzma_isfailed(lzma_ret status)
30
+ {
31
+ return status != 0;
32
+ }
33
+
34
+
35
+ // SECTION: LZMA::Constants
36
+
37
+ static VALUE mConstants;
38
+
39
+ static void
40
+ setup_constants(void)
41
+ {
42
+ mConstants = rb_define_module_under(mLZMA, "Constants");
43
+ rb_include_module(mLZMA, mConstants);
44
+
45
+ #define DEFINE_CONSTANT(NAME, VALUE) \
46
+ { \
47
+ rb_define_const(mConstants, #NAME, VALUE); \
48
+ rb_define_const(mConstants, "LZMA_" #NAME, VALUE); \
49
+ } \
50
+
51
+ DEFINE_CONSTANT(NICE_DEFAULT, SIZET2NUM(64));
52
+ DEFINE_CONSTANT(DEPTH_DEFAULT, SIZET2NUM(0));
53
+
54
+ DEFINE_CONSTANT(PRESET_DEFAULT, UINT2NUM(LZMA_PRESET_DEFAULT));
55
+ DEFINE_CONSTANT(PRESET_LEVEL_MASK, UINT2NUM(LZMA_PRESET_LEVEL_MASK));
56
+ DEFINE_CONSTANT(PRESET_EXTREME, UINT2NUM(LZMA_PRESET_EXTREME));
57
+ DEFINE_CONSTANT(DICT_SIZE_MIN, UINT2NUM(LZMA_DICT_SIZE_MIN));
58
+ DEFINE_CONSTANT(DICT_SIZE_DEFAULT, UINT2NUM(LZMA_DICT_SIZE_DEFAULT));
59
+ DEFINE_CONSTANT(LCLP_MIN, UINT2NUM(LZMA_LCLP_MIN));
60
+ DEFINE_CONSTANT(LCLP_MAX, UINT2NUM(LZMA_LCLP_MAX));
61
+ DEFINE_CONSTANT(LC_DEFAULT, UINT2NUM(LZMA_LC_DEFAULT));
62
+ DEFINE_CONSTANT(LP_DEFAULT, UINT2NUM(LZMA_LP_DEFAULT));
63
+ DEFINE_CONSTANT(PB_MIN, UINT2NUM(LZMA_PB_MIN));
64
+ DEFINE_CONSTANT(PB_MAX, UINT2NUM(LZMA_PB_MAX));
65
+ DEFINE_CONSTANT(PB_DEFAULT, UINT2NUM(LZMA_PB_DEFAULT));
66
+ DEFINE_CONSTANT(MODE_FAST, UINT2NUM(LZMA_MODE_FAST));
67
+ DEFINE_CONSTANT(MODE_NORMAL, UINT2NUM(LZMA_MODE_NORMAL));
68
+ DEFINE_CONSTANT(MF_HC3, UINT2NUM(LZMA_MF_HC3));
69
+ DEFINE_CONSTANT(MF_HC4, UINT2NUM(LZMA_MF_HC4));
70
+ DEFINE_CONSTANT(MF_BT2, UINT2NUM(LZMA_MF_BT2));
71
+ DEFINE_CONSTANT(MF_BT3, UINT2NUM(LZMA_MF_BT3));
72
+ DEFINE_CONSTANT(MF_BT4, UINT2NUM(LZMA_MF_BT4));
73
+
74
+ DEFINE_CONSTANT(CHECK_NONE, UINT2NUM(LZMA_CHECK_NONE));
75
+ DEFINE_CONSTANT(CHECK_CRC32, UINT2NUM(LZMA_CHECK_CRC32));
76
+ DEFINE_CONSTANT(CHECK_CRC64, UINT2NUM(LZMA_CHECK_CRC64));
77
+ DEFINE_CONSTANT(CHECK_SHA256, UINT2NUM(LZMA_CHECK_SHA256));
78
+
79
+ DEFINE_CONSTANT(RUN, UINT2NUM(LZMA_RUN));
80
+ DEFINE_CONSTANT(FULL_FLUSH, UINT2NUM(LZMA_FULL_FLUSH));
81
+ DEFINE_CONSTANT(SYNC_FLUSH, UINT2NUM(LZMA_SYNC_FLUSH));
82
+ DEFINE_CONSTANT(FINISH, UINT2NUM(LZMA_FINISH));
83
+
84
+ #undef DEFINE_CONSTANT
85
+ }
86
+
87
+
88
+ // SECTION: LZMA::Exceptions
89
+
90
+ static VALUE mExceptions;
91
+
92
+ static VALUE eBasicException;
93
+ static VALUE eStreamEnd;
94
+ static VALUE eNoCheck;
95
+ static VALUE eUnsupportedCheck;
96
+ static VALUE eGetCheck;
97
+ static VALUE eMemError;
98
+ static VALUE eMemlimitError;
99
+ static VALUE eFormatError;
100
+ static VALUE eOptionsError;
101
+ static VALUE eDataError;
102
+ static VALUE eBufError;
103
+ static VALUE eProgError;
104
+ static VALUE eFilterTooLong;
105
+ static VALUE eBadPreset;
106
+
107
+ static inline VALUE
108
+ lookup_exception(lzma_ret status)
109
+ {
110
+ switch (status) {
111
+ case LZMA_OK: return Qnil;
112
+ case LZMA_STREAM_END: return eStreamEnd;
113
+ case LZMA_NO_CHECK: return eNoCheck;
114
+ case LZMA_UNSUPPORTED_CHECK: return eUnsupportedCheck;
115
+ case LZMA_GET_CHECK: return eGetCheck;
116
+ case LZMA_MEM_ERROR: return eMemError;
117
+ case LZMA_MEMLIMIT_ERROR: return eMemlimitError;
118
+ case LZMA_FORMAT_ERROR: return eFormatError;
119
+ case LZMA_OPTIONS_ERROR: return eOptionsError;
120
+ case LZMA_DATA_ERROR: return eDataError;
121
+ case LZMA_BUF_ERROR: return eBufError;
122
+ case LZMA_PROG_ERROR: return eProgError;
123
+ default: return rb_eRuntimeError;
124
+ }
125
+ }
126
+
127
+ static void
128
+ setup_exceptions(void)
129
+ {
130
+ mExceptions = rb_define_module_under(mLZMA, "Exceptions");
131
+ rb_include_module(mLZMA, mExceptions);
132
+
133
+ eBasicException = rb_define_class_under(mExceptions, "BasicException", rb_eStandardError);
134
+ rb_define_class_under(mExceptions, "FilterTooLong", eBasicException);
135
+ rb_define_class_under(mExceptions, "BadPreset", eBasicException);
136
+
137
+ #define DEFINE_EXCEPTION(CLASS, STATUS) \
138
+ { \
139
+ e ## CLASS = rb_define_class_under(mExceptions, #CLASS, eBasicException); \
140
+ rb_define_const(e ## CLASS, "STATUS", SIZET2NUM(STATUS)); \
141
+ } \
142
+
143
+ DEFINE_EXCEPTION(StreamEnd, LZMA_STREAM_END);
144
+ DEFINE_EXCEPTION(NoCheck, LZMA_NO_CHECK);
145
+ DEFINE_EXCEPTION(UnsupportedCheck, LZMA_UNSUPPORTED_CHECK);
146
+ DEFINE_EXCEPTION(GetCheck, LZMA_GET_CHECK);
147
+ DEFINE_EXCEPTION(MemError, LZMA_MEM_ERROR);
148
+ DEFINE_EXCEPTION(MemlimitError, LZMA_MEMLIMIT_ERROR);
149
+ DEFINE_EXCEPTION(FormatError, LZMA_FORMAT_ERROR);
150
+ DEFINE_EXCEPTION(OptionsError, LZMA_OPTIONS_ERROR);
151
+ DEFINE_EXCEPTION(DataError, LZMA_DATA_ERROR);
152
+ DEFINE_EXCEPTION(BufError, LZMA_BUF_ERROR);
153
+ DEFINE_EXCEPTION(ProgError, LZMA_PROG_ERROR);
154
+ #undef DEFINE_EXCEPTION
155
+ }
156
+
157
+
158
+ // SECTION: LZMA::Filter
159
+
160
+ static VALUE cFilter;
161
+ static VALUE cBasicLZMA;
162
+ static VALUE cLZMA1;
163
+ static VALUE cLZMA2;
164
+ static VALUE cDelta;
165
+
166
+
167
+ static inline lzma_filter *
168
+ getfilter(VALUE obj)
169
+ {
170
+ lzma_filter *filter;
171
+ Data_Get_Struct(obj, lzma_filter, filter);
172
+ return filter;
173
+ }
174
+
175
+ static void *
176
+ setup_lzma_preset(size_t preset)
177
+ {
178
+ lzma_options_lzma *lzma = xcalloc(sizeof(lzma_options_lzma), 1);
179
+ if (lzma_lzma_preset(lzma, preset)) {
180
+ rb_raise(rb_eArgError,
181
+ "wrong preset level (%d for 0..9) or wrong flag bit(s) (%08x)",
182
+ preset & LZMA_PRESET_LEVEL_MASK,
183
+ preset & ~LZMA_PRESET_LEVEL_MASK & ~LZMA_PRESET_EXTREME);
184
+ }
185
+ return (void *)(lzma);
186
+ }
187
+
188
+ static const char PRIVATE_DICTPRESET[] = "dict_preset";
189
+
190
+ static inline void
191
+ lzma_set_dict_0(lzma_options_lzma *filter, VALUE dict, VALUE self)
192
+ {
193
+ if (NIL_P(dict)) {
194
+ filter->preset_dict = NULL;
195
+ filter->preset_dict_size = 0;
196
+ } else {
197
+ if (TYPE(dict) != T_STRING) {
198
+ rb_raise(rb_eTypeError, "%s", "dict is not a String or nil");
199
+ }
200
+ dict = rb_str_new_frozen(dict);
201
+ filter->preset_dict = (uint8_t *)(RSTRING_PTR(dict));
202
+ filter->preset_dict_size = RSTRING_LEN(dict);
203
+ }
204
+ rb_iv_set(self, PRIVATE_DICTPRESET, dict);
205
+ }
206
+
207
+ static VALUE
208
+ lzma_set_dict(VALUE self, VALUE dict)
209
+ {
210
+ lzma_set_dict_0((lzma_options_lzma *)getfilter(self)->options, dict, self);
211
+ return self;
212
+ }
213
+
214
+ static VALUE
215
+ lzma_get_dict(VALUE self)
216
+ {
217
+ return rb_str_new_shared(rb_iv_get(self, PRIVATE_DICTPRESET));
218
+ }
219
+
220
+
221
+ #define DEFINE_ACCESSOR_ENTITY(NAME, MEMBER, DEFAULT) \
222
+ static inline void \
223
+ lzma_set_ ## NAME ## _0(lzma_options_lzma *filter, VALUE n) \
224
+ { \
225
+ if (NIL_P(n)) { \
226
+ filter->MEMBER = DEFAULT; \
227
+ } else { \
228
+ filter->MEMBER = NUM2UINT(n); \
229
+ } \
230
+ } \
231
+ \
232
+ static VALUE \
233
+ lzma_set_ ## NAME(VALUE self, VALUE n) \
234
+ { \
235
+ lzma_set_ ## NAME ## _0((lzma_options_lzma *)getfilter(self)->options, n); \
236
+ return self; \
237
+ } \
238
+ \
239
+ static VALUE \
240
+ lzma_get_ ## NAME(VALUE self) \
241
+ { \
242
+ return UINT2NUM(((lzma_options_lzma *)getfilter(self)->options)->MEMBER); \
243
+ } \
244
+
245
+ DEFINE_ACCESSOR_ENTITY(dictsize, dict_size, LZMA_DICT_SIZE_DEFAULT) // lzma_set_dictsize_0, lzma_set_dictsize, lzma_set_lc
246
+ DEFINE_ACCESSOR_ENTITY(lc, lc, LZMA_LC_DEFAULT)
247
+ DEFINE_ACCESSOR_ENTITY(lp, lp, LZMA_LP_DEFAULT)
248
+ DEFINE_ACCESSOR_ENTITY(pb, pb, LZMA_PB_DEFAULT)
249
+ DEFINE_ACCESSOR_ENTITY(mode, mode, LZMA_MODE_NORMAL)
250
+ DEFINE_ACCESSOR_ENTITY(nice, nice_len, 64)
251
+ DEFINE_ACCESSOR_ENTITY(mf, mf, LZMA_MF_BT4)
252
+ DEFINE_ACCESSOR_ENTITY(depth, depth, 0)
253
+
254
+ #undef DEFINE_ACCESSOR_ENTITY
255
+
256
+ static void *
257
+ setup_lzma(VALUE obj, uint32_t preset,
258
+ VALUE dictsize, VALUE dictpreset, VALUE lc, VALUE lp, VALUE pb,
259
+ VALUE mode, VALUE nice, VALUE mf, VALUE depth)
260
+ {
261
+ lzma_options_lzma lzma = { 0 };
262
+ if (lzma_lzma_preset(&lzma, preset) != 0) {
263
+ rb_raise(eBadPreset, "bad preset (%08x)", preset);
264
+ }
265
+
266
+ if (RTEST(dictpreset)) { lzma_set_dict_0(&lzma, dictpreset, obj); }
267
+
268
+ #define SETVAR(NAME) \
269
+ if (RTEST(NAME)) { lzma_set_ ## NAME ## _0(&lzma, NAME); } \
270
+
271
+ SETVAR(dictsize);
272
+ SETVAR(lc);
273
+ SETVAR(lp);
274
+ SETVAR(pb);
275
+ SETVAR(mode);
276
+ SETVAR(nice);
277
+ SETVAR(mf);
278
+ SETVAR(depth);
279
+
280
+ #undef SETVAR
281
+
282
+ {
283
+ lzma_options_lzma *p = ALLOC(lzma_options_lzma);
284
+ memcpy(p, &lzma, sizeof(lzma));
285
+ return (void *)(p);
286
+ }
287
+ }
288
+
289
+ static void
290
+ cleanup_filter(lzma_filter *filter)
291
+ {
292
+ if (filter->options) { xfree(filter->options); }
293
+ xfree(filter);
294
+ }
295
+
296
+
297
+ static uint32_t
298
+ getpreset(VALUE preset)
299
+ {
300
+ if (NIL_P(preset)) {
301
+ return LZMA_PRESET_DEFAULT;
302
+ } else {
303
+ return NUM2UINT(preset);
304
+ }
305
+ }
306
+
307
+ /*
308
+ * call-seq:
309
+ * LZMA::Filter.lzma1(....)
310
+ *
311
+ * LZMA::Filter::LZMA1.newを呼ぶための補助機構である
312
+ *
313
+ * LZMA::Filter::LZMA1クラスの .new や #initialize を書き換えた場合はそれに従う
314
+ * (あくまで .new を呼ぶだけである)
315
+ */
316
+ static VALUE
317
+ lzma1_new(int argc, VALUE argv[], VALUE self)
318
+ {
319
+ return rb_class_new_instance(argc, argv, cLZMA1);
320
+ }
321
+
322
+ /*
323
+ * call-seq:
324
+ * LZMA::Filter.lzma2(...)
325
+ *
326
+ * LZMA::Filter::LZMA2.new を呼ぶための補助機構である
327
+ *
328
+ * LZMA::Filter::LZMA2クラスの .new や #initialize を書き換えた場合はそれに従う
329
+ * (あくまで .new を呼ぶだけである)
330
+ */
331
+ static VALUE
332
+ lzma2_new(int argc, VALUE argv[], VALUE self)
333
+ {
334
+ return rb_class_new_instance(argc, argv, cLZMA2);
335
+ }
336
+
337
+ /*
338
+ * call-seq:
339
+ * LZMA::Filter.delta(....)
340
+ *
341
+ * LZMA::Filter::Delta.newを呼ぶための補助機構である
342
+ *
343
+ * LZMA::Filter::Deltaクラスの .new や #initialize を書き換えた場合はそれに従う
344
+ * (あくまで .new を呼ぶだけである)
345
+ */
346
+ static VALUE
347
+ delta_new(int argc, VALUE argv[], VALUE self)
348
+ {
349
+ return rb_class_new_instance(argc, argv, cDelta);
350
+ }
351
+
352
+
353
+
354
+ static inline VALUE
355
+ filter_alloc(VALUE klass, lzma_vli id)
356
+ {
357
+ lzma_filter *filter;
358
+ VALUE obj = Data_Make_Struct(klass, lzma_filter, NULL, cleanup_filter, filter);
359
+ memset(filter, 0, sizeof(*filter));
360
+ filter->id = id;
361
+ return obj;
362
+ }
363
+
364
+ static VALUE
365
+ lzma1_alloc(VALUE klass)
366
+ {
367
+ return filter_alloc(klass, LZMA_FILTER_LZMA1);
368
+ }
369
+
370
+ static VALUE
371
+ lzma2_alloc(VALUE klass)
372
+ {
373
+ return filter_alloc(klass, LZMA_FILTER_LZMA2);
374
+ }
375
+
376
+ static VALUE
377
+ delta_alloc(VALUE klass)
378
+ {
379
+ return filter_alloc(cDelta, LZMA_FILTER_DELTA);
380
+ }
381
+
382
+ /*
383
+ * call-seq:
384
+ * LZMA::Filter::Delta.new(dist = LZMA::DELTA_DIST_MIN)
385
+ *
386
+ * 差分フィルタ設定オブジェクトを返す。
387
+ *
388
+ * distは1要素あたりのバイト長で、1以上を指定する。
389
+ *
390
+ * 使用する場合多くの場合1で十分だろうし、音楽CDの音声データであれば2を指定するのがいいだろう。
391
+ *
392
+ * しかし元のデータによっては圧縮効率を低下させることがあるため、常に適用することはしないほうがいい。
393
+ */
394
+ static VALUE
395
+ delta_init(int argc, VALUE argv[], VALUE self)
396
+ {
397
+ lzma_filter *filter = getfilter(self);
398
+ lzma_options_delta *delta = ALLOC(lzma_options_delta);
399
+ memset(delta, 0, sizeof(*delta));
400
+
401
+ VALUE preset = Qnil;
402
+ rb_scan_args(argc, argv, "01", &preset);
403
+ delta->type = LZMA_DELTA_TYPE_BYTE;
404
+ delta->dist = NIL_P(preset) ? LZMA_DELTA_DIST_MIN : NUM2UINT(preset);
405
+ filter->options = delta;
406
+ return self;
407
+ }
408
+
409
+ /*
410
+ * call-seq:
411
+ * LZMA::Filter::BasicLZMA.new(preset = LZMA::PRESET_DEFAULT, opts = { .... } ) -> filter
412
+ *
413
+ * フィルタ設定オブジェクトを返す。
414
+ *
415
+ * この段階で各値の確認を行うことはせず、*encoderに渡すときに初めて確認される
416
+ *
417
+ * 引数::
418
+ * 引数は、presetは整数で、続くoptsはハッシュであり、細かい調整を行う場合に指定する。
419
+ *
420
+ * どちらも任意に省略可能であり、presetを省略してoptsを指定することも可能である。
421
+ *
422
+ * preset:: プリセット値 (≒圧縮レベル) を0-9の範囲で指定する。既定値はLZMA::PRESET_DEFAULTである。
423
+ * dictsize:: 既定値はLZMA::DICT_SIZE_DEFAULT
424
+ * presetdict:: 既定値はnil
425
+ * lc:: 既定値はLZMA::LC_DEFAULT
426
+ * lp:: 既定値はLZMA::LP_DEFAULT
427
+ * pb:: 既定値はLZMA::PB_DEFAULT
428
+ * mode:: 既定値はLZMA::MODE_NORMAL
429
+ * nice:: 既定値はLZMA::NICE_DEFAULT
430
+ * mf:: 既定値はLZMA::MF_BT4
431
+ * depth:: 既定値はLZMA::DEPTH_DEFAULT
432
+ */
433
+ static VALUE
434
+ lzma_init(int argc, VALUE argv[], VALUE self)
435
+ {
436
+ VALUE preset = Qnil;
437
+ VALUE opts = Qnil;
438
+ rb_scan_args(argc, argv, "01:", &preset, &opts);
439
+ lzma_filter *filter = getfilter(self);
440
+ if (NIL_P(opts)) {
441
+ filter->options = setup_lzma_preset(getpreset(preset));
442
+ } else {
443
+ filter->options = setup_lzma(self, getpreset(preset),
444
+ rb_hash_lookup(opts, symDICTSIZE),
445
+ rb_hash_lookup(opts, symPRESETDICT),
446
+ rb_hash_lookup(opts, symLC),
447
+ rb_hash_lookup(opts, symLP),
448
+ rb_hash_lookup(opts, symPB),
449
+ rb_hash_lookup(opts, symMODE),
450
+ rb_hash_lookup(opts, symNICE),
451
+ rb_hash_lookup(opts, symMF),
452
+ rb_hash_lookup(opts, symDEPTH));
453
+ }
454
+ return self;
455
+ }
456
+
457
+ /*
458
+ * Document-method: LZMA::Filter::BasicLZMA#dictsize
459
+ *
460
+ * call-seq:
461
+ * LZMA::Filter::BasicLZMA#dictsize -> 辞書サイズ (バイト長)
462
+ *
463
+ * 様々なフィルタ値の設定・取り出しを行う
464
+ */
465
+ static void
466
+ setup_filter(void)
467
+ {
468
+ cFilter = rb_define_class_under(mLZMA, "Filter", rb_cObject);
469
+ rb_undef_alloc_func(cFilter);
470
+ rb_define_singleton_method(cFilter, "lzma1", RUBY_METHOD_FUNC(lzma1_new), -1);
471
+ rb_define_singleton_method(cFilter, "lzma2", RUBY_METHOD_FUNC(lzma2_new), -1);
472
+ rb_define_singleton_method(cFilter, "delta", RUBY_METHOD_FUNC(delta_new), -1);
473
+
474
+ cBasicLZMA = rb_define_class_under(cFilter, "BasicLZMA", cFilter);
475
+ rb_define_method(cBasicLZMA, "initialize", lzma_init, -1);
476
+
477
+ cLZMA1 = rb_define_class_under(cFilter, "LZMA1", cBasicLZMA);
478
+ rb_define_alloc_func(cLZMA1, lzma1_alloc);
479
+
480
+ cLZMA2 = rb_define_class_under(cFilter, "LZMA2", cBasicLZMA);
481
+ rb_define_alloc_func(cLZMA2, lzma2_alloc);
482
+
483
+ cDelta = rb_define_class_under(cFilter, "Delta", cFilter);
484
+ rb_define_alloc_func(cDelta, delta_alloc);
485
+ rb_define_method(cDelta, "initialize", delta_init, -1);
486
+
487
+ #define DEF_ACCESSOR(CLASS, NAME) \
488
+ rb_define_method(CLASS, #NAME, lzma_get_ ## NAME, 0); \
489
+ rb_define_method(CLASS, #NAME "=", lzma_set_ ## NAME, 1); \
490
+
491
+ DEF_ACCESSOR(cBasicLZMA, dictsize);
492
+ DEF_ACCESSOR(cBasicLZMA, dict);
493
+ DEF_ACCESSOR(cBasicLZMA, lc);
494
+ DEF_ACCESSOR(cBasicLZMA, lp);
495
+ DEF_ACCESSOR(cBasicLZMA, pb);
496
+ DEF_ACCESSOR(cBasicLZMA, mode);
497
+ DEF_ACCESSOR(cBasicLZMA, nice);
498
+ DEF_ACCESSOR(cBasicLZMA, mf);
499
+ DEF_ACCESSOR(cBasicLZMA, depth);
500
+
501
+ #undef DEF_ACCESSOR
502
+ }
503
+
504
+
505
+ // SECTION: LZMA::Stream
506
+
507
+ static VALUE cStream;
508
+ static VALUE cEncoder;
509
+ static VALUE cDecoder;
510
+ static VALUE cAutoDecoder;
511
+ static VALUE cRawEncoder;
512
+ static VALUE cRawDecoder;
513
+
514
+
515
+ #define LZMA_TEST(STATUS) \
516
+ { \
517
+ lzma_ret _status = (STATUS); \
518
+ if (lzma_isfailed(_status)) { \
519
+ VALUE exc = lookup_exception(_status); \
520
+ rb_exc_raise(rb_exc_new3(exc, rb_class_name(exc))); \
521
+ } \
522
+ } \
523
+
524
+ static inline void
525
+ filter_copy(lzma_filter *dest, VALUE filter)
526
+ {
527
+ memcpy(dest, getfilter(filter), sizeof(*dest));
528
+ }
529
+
530
+ static void
531
+ stream_clear(lzma_stream *stream)
532
+ {
533
+ const lzma_stream init = LZMA_STREAM_INIT;
534
+ memcpy(stream, &init, sizeof(init));
535
+ }
536
+
537
+ static inline lzma_stream *
538
+ getstream(VALUE lzma)
539
+ {
540
+ lzma_stream *stream;
541
+ Data_Get_Struct(lzma, lzma_stream, stream);
542
+ return stream;
543
+ }
544
+
545
+ static inline void
546
+ stream_cleanup(lzma_stream *stream)
547
+ {
548
+ lzma_end(stream);
549
+ xfree(stream);
550
+ }
551
+
552
+
553
+ static inline int
554
+ is_sync(size_t sync)
555
+ {
556
+ return (sync == LZMA_SYNC_FLUSH || sync == LZMA_FULL_FLUSH || sync == LZMA_FINISH);
557
+ }
558
+
559
+
560
+ struct stream_update_args
561
+ {
562
+ lzma_stream *stream;
563
+ lzma_action action;
564
+ const uint8_t *src;
565
+ size_t srclen;
566
+ };
567
+
568
+ static VALUE
569
+ stream_update_1(struct stream_update_args *args)
570
+ {
571
+ VALUE dest = rb_str_new("", 0);
572
+ uint8_t buf[4 * 1024];
573
+ args->stream->next_in = args->src;
574
+ args->stream->avail_in = args->srclen;
575
+ while (args->stream->avail_in > 0 || is_sync(args->action)) {
576
+ do {
577
+ rb_thread_check_ints();
578
+ args->stream->next_out = buf;
579
+ args->stream->avail_out = sizeof(buf);
580
+ lzma_ret status = lzma_code(args->stream, args->action);
581
+ if (status == LZMA_STREAM_END) {
582
+ rb_str_buf_cat(dest, (const char *)buf, args->stream->next_out - buf);
583
+ return dest;
584
+ }
585
+
586
+ LZMA_TEST(status);
587
+ rb_str_buf_cat(dest, (const char *)buf, args->stream->next_out - buf);
588
+ } while (args->stream->next_out - buf > 0);
589
+ }
590
+ return dest;
591
+ }
592
+
593
+ static inline VALUE
594
+ stream_update_2(struct stream_update_args *args)
595
+ {
596
+ return rb_thread_blocking_region((VALUE (*)(void *))stream_update_1, args, RUBY_UBF_IO, NULL);
597
+ }
598
+
599
+ static inline VALUE
600
+ stream_update_3(VALUE src)
601
+ {
602
+ rb_str_unlocktmp(src);
603
+ return Qnil;
604
+ }
605
+
606
+ static inline VALUE
607
+ stream_update_0(lzma_stream *stream, lzma_action action, VALUE src)
608
+ {
609
+ if (RTEST(src)) {
610
+ StringValue(src);
611
+ rb_str_locktmp(src);
612
+ struct stream_update_args args = {
613
+ stream, action,
614
+ (const uint8_t *)RSTRING_PTR(src), RSTRING_LEN(src),
615
+ };
616
+ return rb_ensure(stream_update_2, (VALUE)&args, stream_update_3, src);
617
+ } else {
618
+ struct stream_update_args args = {
619
+ stream, action, NULL, 0,
620
+ };
621
+ return stream_update_2(&args);
622
+ }
623
+ }
624
+
625
+ /*
626
+ * call-seq:
627
+ * LZMA::Stream#update(src, flush = LZMA::RUN)
628
+ *
629
+ * データストリームとして渡されたsrcを圧縮/伸張します。
630
+ *
631
+ * [RETURN] Stringインスタンス
632
+ * [EXCEPTION] LZMA::Exceptions::BasicException
633
+ */
634
+ static VALUE
635
+ stream_update(int argc, VALUE argv[], VALUE self)
636
+ {
637
+ VALUE src, flush1;
638
+ int flush;
639
+ if (rb_scan_args(argc, argv, "11", &src, &flush1) == 1) {
640
+ flush = LZMA_RUN;
641
+ } else {
642
+ flush = NUM2INT(flush1);
643
+ }
644
+ lzma_stream *stream = getstream(self);
645
+ return stream_update_0(stream, flush, src);
646
+ }
647
+
648
+ /*
649
+ * call-seq:
650
+ * LZMA::Stream#flush(fullsync = false)
651
+ */
652
+ static VALUE
653
+ stream_flush(int argc, VALUE argv[], VALUE self)
654
+ {
655
+ VALUE fullsync = Qfalse;
656
+ rb_scan_args(argc, argv, "01", &fullsync);
657
+ lzma_stream *stream = getstream(self);
658
+ size_t sync = RTEST(fullsync) ? LZMA_FULL_FLUSH : LZMA_SYNC_FLUSH;
659
+ return stream_update_0(stream, sync, Qnil);
660
+ }
661
+
662
+ /*
663
+ * call-seq:
664
+ * LZMA::Stream#finish
665
+ */
666
+ static VALUE
667
+ stream_finish(VALUE self)
668
+ {
669
+ lzma_stream *stream = getstream(self);
670
+ VALUE dest = stream_update_0(stream, LZMA_FINISH, Qnil);
671
+
672
+ lzma_end(stream);
673
+ stream_clear(stream);
674
+
675
+ return dest;
676
+ }
677
+
678
+
679
+
680
+ static VALUE
681
+ stream_alloc(VALUE klass)
682
+ {
683
+ lzma_stream *stream;
684
+ VALUE obj = Data_Make_Struct(klass, lzma_stream, NULL, stream_cleanup, stream);
685
+ stream_clear(stream);
686
+ return obj;
687
+ }
688
+
689
+ // filters0はLZMA::Filterクラスのinstanceを与えることができる
690
+ static void
691
+ filter_setup(lzma_filter filter[LZMA_FILTERS_MAX + 1], VALUE filters0[], VALUE *filters0end)
692
+ {
693
+ if ((filters0end - filters0) > LZMA_FILTERS_MAX) {
694
+ rb_raise(eFilterTooLong, "filter chain too long (max %d, but given %d)",
695
+ LZMA_FILTERS_MAX, filters0end - filters0);
696
+ }
697
+ for (; filters0 < filters0end; filters0 ++, filter ++) {
698
+ VALUE f = *filters0;
699
+ if (!rb_obj_is_kind_of(f, cFilter)) {
700
+ rb_raise(rb_eTypeError, "%s", "not a filter");
701
+ }
702
+ filter_copy(filter, f);
703
+ }
704
+ filter->id = LZMA_VLI_UNKNOWN;
705
+ filter->options = NULL;
706
+ }
707
+
708
+
709
+ // LZMA::Stream.encoder(filter1, filter2, ...., filterN, check: CRC64)
710
+ static VALUE
711
+ encoder_init(int argc, VALUE argv[], VALUE self)
712
+ {
713
+ VALUE vcheck;
714
+ rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &vcheck);
715
+ uint32_t check;
716
+ if (NIL_P(vcheck)) {
717
+ check = LZMA_CHECK_CRC64;
718
+ } else {
719
+ check = NUM2UINT(vcheck);
720
+ argc --;
721
+ }
722
+ lzma_filter filters[LZMA_FILTERS_MAX + 1];
723
+ memset(filters, 0, sizeof(filters));
724
+ filter_setup(filters, argv, argv + argc);
725
+
726
+ lzma_stream *stream = getstream(self);
727
+ LZMA_TEST(lzma_stream_encoder(stream, filters, check));
728
+
729
+ return self;
730
+ }
731
+
732
+ /*
733
+ * call-seq:
734
+ * LZMA::Stream::AutoDecoder.initialize(memlimit = nil, flags = nil)
735
+ */
736
+ static VALUE
737
+ autodecoder_init(int argc, VALUE argv[], VALUE self)
738
+ {
739
+ VALUE memlimit0 = Qnil;
740
+ VALUE flags0 = Qnil;
741
+ uint64_t memlimit = UINT64_MAX;
742
+ uint32_t flags = 0;
743
+ rb_scan_args(argc, argv, "02", &memlimit0, &flags0);
744
+ if (!NIL_P(flags0)) { flags = NUM2SIZET(flags0); }
745
+ if (!NIL_P(memlimit0)) { memlimit = NUM2SIZET(memlimit0); }
746
+
747
+ lzma_stream *stream = getstream(self);
748
+ LZMA_TEST(lzma_auto_decoder(stream, memlimit, flags));
749
+
750
+ return self;
751
+ }
752
+
753
+ /*
754
+ * call-seq:
755
+ * LZMA::Stream::Decoder.initialize(memlimit = nil, flags = nil)
756
+ */
757
+ static VALUE
758
+ decoder_init(int argc, VALUE argv[], VALUE self)
759
+ {
760
+ VALUE memlimit0 = Qnil;
761
+ VALUE flags0 = Qnil;
762
+ uint64_t memlimit = UINT64_MAX;
763
+ uint32_t flags = 0;
764
+ rb_scan_args(argc, argv, "02", &memlimit0, &flags0);
765
+ if (!NIL_P(flags0)) { flags = NUM2SIZET(flags0); }
766
+ if (!NIL_P(memlimit0)) { memlimit = NUM2SIZET(memlimit0); }
767
+
768
+ lzma_stream *stream = getstream(self);
769
+ LZMA_TEST(lzma_stream_decoder(stream, memlimit, flags));
770
+
771
+ return self;
772
+ }
773
+
774
+ /*
775
+ * call-seq:
776
+ * LZMA::Stream::RawEncoder.initialize(filter1 [ , filter2 [ , .... ] ]) -> encoder
777
+ *
778
+ * 生の (xzヘッダなどの付かない) LZMA1/2ストリームを構成する圧縮器機を生成する。
779
+ *
780
+ * filterは1つ以上4つまでを与える。
781
+ */
782
+ static VALUE
783
+ rawencoder_init(int argc, VALUE argv[], VALUE self)
784
+ {
785
+ if (argc < 1 || argc > 4) {
786
+ rb_scan_args(argc, argv, "13", NULL, NULL, NULL, NULL);
787
+ }
788
+ lzma_filter filters[LZMA_FILTERS_MAX + 1];
789
+ memset(filters, 0, sizeof(filters));
790
+ filter_setup(filters, argv, argv + argc);
791
+
792
+ lzma_stream *stream = getstream(self);
793
+ LZMA_TEST(lzma_raw_encoder(stream, filters));
794
+
795
+ return self;
796
+ }
797
+
798
+ /*
799
+ * call-seq:
800
+ * LZMA::Stream::RawDecoder.initialize(filter1 [ , filter2 [ , .... ] ])
801
+ */
802
+ static VALUE
803
+ rawdecoder_init(int argc, VALUE argv[], VALUE self)
804
+ {
805
+ if (argc < 1 || argc > 4) {
806
+ rb_scan_args(argc, argv, "13", NULL, NULL, NULL, NULL);
807
+ }
808
+ lzma_filter filters[LZMA_FILTERS_MAX + 1];
809
+ memset(filters, 0, sizeof(filters));
810
+ filter_setup(filters, argv, argv + argc);
811
+
812
+ lzma_stream *stream = getstream(self);
813
+ LZMA_TEST(lzma_raw_decoder(stream, filters));
814
+
815
+ return self;
816
+ }
817
+
818
+ static void
819
+ setup_stream(void)
820
+ {
821
+ cStream = rb_define_class_under(mLZMA, "Stream", rb_cObject);
822
+ rb_undef_alloc_func(cStream);
823
+ rb_define_method(cStream, "update", stream_update, -1);
824
+ rb_define_method(cStream, "flush", stream_flush, -1);
825
+ rb_define_method(cStream, "finish", stream_finish, 0);
826
+
827
+ cEncoder = rb_define_class_under(cStream, "Encoder", cStream);
828
+ rb_define_alloc_func(cEncoder, stream_alloc);
829
+ rb_define_method(cEncoder, "initialize", RUBY_METHOD_FUNC(encoder_init), -1);
830
+
831
+ cDecoder = rb_define_class_under(cStream, "Decoder", cStream);
832
+ rb_define_alloc_func(cDecoder, stream_alloc);
833
+ rb_define_method(cDecoder, "initialize", RUBY_METHOD_FUNC(decoder_init), -1);
834
+
835
+ cAutoDecoder = rb_define_class_under(cStream, "AutoDecoder", cStream);
836
+ rb_define_alloc_func(cAutoDecoder, stream_alloc);
837
+ rb_define_method(cAutoDecoder, "initialize", RUBY_METHOD_FUNC(autodecoder_init), -1);
838
+
839
+ cRawEncoder = rb_define_class_under(cStream, "RawEncoder", cStream);
840
+ rb_define_alloc_func(cRawEncoder, stream_alloc);
841
+ rb_define_method(cRawEncoder, "initialize", RUBY_METHOD_FUNC(rawencoder_init), -1);
842
+
843
+ cRawDecoder = rb_define_class_under(cStream, "RawDecoder", cStream);
844
+ rb_define_alloc_func(cRawDecoder, stream_alloc);
845
+ rb_define_method(cRawDecoder, "initialize", RUBY_METHOD_FUNC(rawdecoder_init), -1);
846
+ }
847
+
848
+
849
+ // SECTION: LZMA::Index
850
+
851
+
852
+ static VALUE cIndex;
853
+ static VALUE cIEncoder;
854
+ static VALUE cIDecoder;
855
+
856
+ static VALUE
857
+ iencoder_alloc(VALUE klass)
858
+ {
859
+ rb_raise(rb_eNotImpError, "%s", "IMPLEMENT ME!");
860
+ }
861
+
862
+ static VALUE
863
+ iencoder_init(int argc, VALUE argv[], VALUE self)
864
+ {
865
+ rb_raise(rb_eNotImpError, "%s", "IMPLEMENT ME!");
866
+ }
867
+
868
+ static VALUE
869
+ idecoder_alloc(VALUE klass)
870
+ {
871
+ rb_raise(rb_eNotImpError, "%s", "IMPLEMENT ME!");
872
+ }
873
+
874
+ static VALUE
875
+ idecoder_init(int argc, VALUE argv[], VALUE self)
876
+ {
877
+ rb_raise(rb_eNotImpError, "%s", "IMPLEMENT ME!");
878
+ }
879
+
880
+
881
+ static void
882
+ setup_index(void)
883
+ {
884
+ cIndex = rb_define_class_under(mLZMA, "Index", rb_cObject);
885
+ rb_undef_alloc_func(cIndex);
886
+
887
+ cIEncoder = rb_define_class_under(cIndex, "Encoder", cIndex);
888
+ rb_define_alloc_func(cIEncoder, iencoder_alloc);
889
+ rb_define_method(cIEncoder, "initialize", RUBY_METHOD_FUNC(iencoder_init), -1);
890
+
891
+ cIDecoder = rb_define_class_under(cIndex, "Decoder", cIndex);
892
+ rb_define_alloc_func(cIDecoder, idecoder_alloc);
893
+ rb_define_method(cIDecoder, "initialize", RUBY_METHOD_FUNC(idecoder_init), -1);
894
+ }
895
+
896
+
897
+ // SECTION: LZMA::Utils
898
+
899
+ struct utils_crc32_args
900
+ {
901
+ const uint8_t *ptr;
902
+ size_t len;
903
+ uint32_t crc;
904
+ };
905
+
906
+ static VALUE
907
+ utils_crc32_update(struct utils_crc32_args *args)
908
+ {
909
+ return UINT2NUM(lzma_crc32(args->ptr, args->len, args->crc));
910
+ }
911
+
912
+ /*
913
+ * call-seq:
914
+ * LZMA::Utils.crc32(string, crc = 0)
915
+ *
916
+ * liblzmaに含まれるlzma_crc32を呼び出します。
917
+ */
918
+ static VALUE
919
+ utils_crc32(int argc, VALUE argv[], VALUE self)
920
+ {
921
+ VALUE src, crc;
922
+ rb_scan_args(argc, argv, "11", &src, &crc);
923
+
924
+ StringValue(src);
925
+ rb_str_locktmp(src);
926
+
927
+ struct utils_crc32_args args = {
928
+ (const uint8_t *)RSTRING_PTR(src),
929
+ RSTRING_LEN(src),
930
+ NIL_P(crc) ? 0 : NUM2UINT(crc),
931
+ };
932
+
933
+ crc = rb_thread_blocking_region((VALUE (*)(void *))utils_crc32_update, &args, RUBY_UBF_IO, NULL);
934
+
935
+ rb_str_unlocktmp(src);
936
+
937
+ return crc;
938
+ }
939
+
940
+
941
+
942
+ struct utils_crc64_args
943
+ {
944
+ const uint8_t *ptr;
945
+ size_t len;
946
+ uint64_t crc;
947
+ };
948
+
949
+ static VALUE
950
+ utils_crc64_update(struct utils_crc64_args *args)
951
+ {
952
+ return ULL2NUM(lzma_crc64(args->ptr, args->len, args->crc));
953
+ }
954
+
955
+ /*
956
+ * call-seq:
957
+ * LZMA::Utils.crc64(string, crc = 0)
958
+ *
959
+ * liblzmaに含まれるlzma_crc64を呼び出します。
960
+ */
961
+ static VALUE
962
+ utils_crc64(int argc, VALUE argv[], VALUE self)
963
+ {
964
+ VALUE src, crc;
965
+ rb_scan_args(argc, argv, "11", &src, &crc);
966
+
967
+ StringValue(src);
968
+ rb_str_locktmp(src);
969
+
970
+ struct utils_crc64_args args = {
971
+ (const uint8_t *)RSTRING_PTR(src),
972
+ RSTRING_LEN(src),
973
+ NIL_P(crc) ? 0 : NUM2ULL(crc),
974
+ };
975
+
976
+ crc = rb_thread_blocking_region((VALUE (*)(void *))utils_crc64_update, &args, RUBY_UBF_IO, NULL);
977
+
978
+ rb_str_unlocktmp(src);
979
+
980
+ return crc;
981
+ }
982
+
983
+
984
+ static VALUE mUtils;
985
+
986
+ static void
987
+ setup_utils(void)
988
+ {
989
+ mUtils = rb_define_module_under(mLZMA, "Utils");
990
+ rb_include_module(mLZMA, mUtils);
991
+ rb_extend_object(mLZMA, mUtils);
992
+
993
+ // rb_define_module_functionを使わない理由は、rb_define_module_functionで定義すると
994
+ // インスタンスメソッドがprivateで定義されるため、その対策。
995
+
996
+ rb_extend_object(mUtils, mUtils);
997
+
998
+ rb_define_method(mUtils, "crc32", RUBY_METHOD_FUNC(utils_crc32), -1);
999
+ rb_define_method(mUtils, "crc64", RUBY_METHOD_FUNC(utils_crc64), -1);
1000
+ }
1001
+
1002
+
1003
+ // SECTION: LZMA
1004
+
1005
+ void
1006
+ Init_liblzma(void)
1007
+ {
1008
+ symDICTSIZE = ID2SYM(rb_intern("dict_size"));
1009
+ symPRESETDICT = ID2SYM(rb_intern("preset_dict"));
1010
+ symLC = ID2SYM(rb_intern("lc"));
1011
+ symLP = ID2SYM(rb_intern("lp"));
1012
+ symPB = ID2SYM(rb_intern("pb"));
1013
+ symMODE = ID2SYM(rb_intern("mode"));
1014
+ symNICE = ID2SYM(rb_intern("nice"));
1015
+ symMF = ID2SYM(rb_intern("mf"));
1016
+ symDEPTH = ID2SYM(rb_intern("depth"));
1017
+ symCHECK = ID2SYM(rb_intern("check"));
1018
+
1019
+ mLZMA = rb_define_module("LZMA");
1020
+
1021
+ setup_utils();
1022
+ setup_constants();
1023
+ setup_exceptions();
1024
+ setup_filter();
1025
+ setup_stream();
1026
+ setup_index();
1027
+ }