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.
- data/README.txt +42 -0
- data/ext/extconf.rb +27 -0
- data/ext/liblzma.c +1237 -0
- data/lib/1.9.1/liblzma.so +0 -0
- data/lib/2.0.0/liblzma.so +0 -0
- data/lib/liblzma.rb +222 -0
- data/samples/01-easy_using.rb +58 -0
- data/samples/02-streaming.rb +82 -0
- metadata +59 -0
data/README.txt
ADDED
@@ -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 ライセンスの下で利用できます。
|
data/ext/extconf.rb
ADDED
@@ -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")
|
data/ext/liblzma.c
ADDED
@@ -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
|
+
}
|