liblzma 0.3-x86-mingw32

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