liblzma 0.3-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.
@@ -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
+ }