extlzham 0.0.1.PROTOTYPE
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.
- checksums.yaml +7 -0
- data/LICENSE.md +27 -0
- data/README.md +21 -0
- data/Rakefile +143 -0
- data/contrib/lzham/LICENSE +22 -0
- data/contrib/lzham/README.md +209 -0
- data/contrib/lzham/include/lzham.h +781 -0
- data/contrib/lzham/lzhamcomp/lzham_comp.h +38 -0
- data/contrib/lzham/lzhamcomp/lzham_lzbase.cpp +244 -0
- data/contrib/lzham/lzhamcomp/lzham_lzbase.h +45 -0
- data/contrib/lzham/lzhamcomp/lzham_lzcomp.cpp +608 -0
- data/contrib/lzham/lzhamcomp/lzham_lzcomp_internal.cpp +1966 -0
- data/contrib/lzham/lzhamcomp/lzham_lzcomp_internal.h +472 -0
- data/contrib/lzham/lzhamcomp/lzham_lzcomp_state.cpp +1413 -0
- data/contrib/lzham/lzhamcomp/lzham_match_accel.cpp +562 -0
- data/contrib/lzham/lzhamcomp/lzham_match_accel.h +146 -0
- data/contrib/lzham/lzhamcomp/lzham_null_threading.h +97 -0
- data/contrib/lzham/lzhamcomp/lzham_pthreads_threading.cpp +229 -0
- data/contrib/lzham/lzhamcomp/lzham_pthreads_threading.h +520 -0
- data/contrib/lzham/lzhamcomp/lzham_threading.h +12 -0
- data/contrib/lzham/lzhamcomp/lzham_win32_threading.cpp +220 -0
- data/contrib/lzham/lzhamcomp/lzham_win32_threading.h +368 -0
- data/contrib/lzham/lzhamdecomp/lzham_assert.cpp +66 -0
- data/contrib/lzham/lzhamdecomp/lzham_assert.h +40 -0
- data/contrib/lzham/lzhamdecomp/lzham_checksum.cpp +73 -0
- data/contrib/lzham/lzhamdecomp/lzham_checksum.h +13 -0
- data/contrib/lzham/lzhamdecomp/lzham_config.h +23 -0
- data/contrib/lzham/lzhamdecomp/lzham_core.h +264 -0
- data/contrib/lzham/lzhamdecomp/lzham_decomp.h +37 -0
- data/contrib/lzham/lzhamdecomp/lzham_helpers.h +54 -0
- data/contrib/lzham/lzhamdecomp/lzham_huffman_codes.cpp +262 -0
- data/contrib/lzham/lzhamdecomp/lzham_huffman_codes.h +14 -0
- data/contrib/lzham/lzhamdecomp/lzham_lzdecomp.cpp +1527 -0
- data/contrib/lzham/lzhamdecomp/lzham_lzdecompbase.cpp +131 -0
- data/contrib/lzham/lzhamdecomp/lzham_lzdecompbase.h +89 -0
- data/contrib/lzham/lzhamdecomp/lzham_math.h +142 -0
- data/contrib/lzham/lzhamdecomp/lzham_mem.cpp +284 -0
- data/contrib/lzham/lzhamdecomp/lzham_mem.h +112 -0
- data/contrib/lzham/lzhamdecomp/lzham_platform.cpp +157 -0
- data/contrib/lzham/lzhamdecomp/lzham_platform.h +284 -0
- data/contrib/lzham/lzhamdecomp/lzham_prefix_coding.cpp +351 -0
- data/contrib/lzham/lzhamdecomp/lzham_prefix_coding.h +146 -0
- data/contrib/lzham/lzhamdecomp/lzham_symbol_codec.cpp +1484 -0
- data/contrib/lzham/lzhamdecomp/lzham_symbol_codec.h +556 -0
- data/contrib/lzham/lzhamdecomp/lzham_timer.cpp +147 -0
- data/contrib/lzham/lzhamdecomp/lzham_timer.h +99 -0
- data/contrib/lzham/lzhamdecomp/lzham_traits.h +141 -0
- data/contrib/lzham/lzhamdecomp/lzham_types.h +97 -0
- data/contrib/lzham/lzhamdecomp/lzham_utils.h +58 -0
- data/contrib/lzham/lzhamdecomp/lzham_vector.cpp +75 -0
- data/contrib/lzham/lzhamdecomp/lzham_vector.h +588 -0
- data/contrib/lzham/lzhamlib/lzham_lib.cpp +179 -0
- data/examples/basic.rb +48 -0
- data/ext/extconf.rb +26 -0
- data/ext/extlzham.c +741 -0
- data/gemstub.rb +22 -0
- data/lib/extlzham/version.rb +5 -0
- data/lib/extlzham.rb +153 -0
- metadata +135 -0
data/ext/extlzham.c
ADDED
@@ -0,0 +1,741 @@
|
|
1
|
+
#include <stdint.h>
|
2
|
+
#include <ruby.h>
|
3
|
+
#include <ruby/thread.h>
|
4
|
+
#include <lzham.h>
|
5
|
+
|
6
|
+
static VALUE mLZHAM;
|
7
|
+
static VALUE eError;
|
8
|
+
static VALUE cEncoder;
|
9
|
+
static VALUE cDecoder;
|
10
|
+
static VALUE mConsts;
|
11
|
+
|
12
|
+
static ID ID_op_lshift;
|
13
|
+
static ID IDdictsize;
|
14
|
+
static ID IDlevel;
|
15
|
+
static ID IDtable_update_rate;
|
16
|
+
static ID IDthreads;
|
17
|
+
static ID IDflags;
|
18
|
+
static ID IDtable_max_update_interval;
|
19
|
+
static ID IDtable_update_interval_slow_rate;
|
20
|
+
|
21
|
+
enum {
|
22
|
+
WORKBUF_SIZE = 256 * 1024, /* 256 KiB */
|
23
|
+
};
|
24
|
+
|
25
|
+
#define SET_MESSAGE(MESG, CONST) \
|
26
|
+
case CONST: \
|
27
|
+
MESG = #CONST; \
|
28
|
+
break \
|
29
|
+
|
30
|
+
static inline void
|
31
|
+
aux_encode_error(lzham_compress_status_t status)
|
32
|
+
{
|
33
|
+
const char *mesg;
|
34
|
+
switch (status) {
|
35
|
+
SET_MESSAGE(mesg, LZHAM_COMP_STATUS_NOT_FINISHED);
|
36
|
+
SET_MESSAGE(mesg, LZHAM_COMP_STATUS_NEEDS_MORE_INPUT);
|
37
|
+
SET_MESSAGE(mesg, LZHAM_COMP_STATUS_HAS_MORE_OUTPUT);
|
38
|
+
SET_MESSAGE(mesg, LZHAM_COMP_STATUS_FIRST_SUCCESS_OR_FAILURE_CODE);
|
39
|
+
SET_MESSAGE(mesg, LZHAM_COMP_STATUS_FIRST_FAILURE_CODE);
|
40
|
+
SET_MESSAGE(mesg, LZHAM_COMP_STATUS_FAILED_INITIALIZING);
|
41
|
+
SET_MESSAGE(mesg, LZHAM_COMP_STATUS_INVALID_PARAMETER);
|
42
|
+
SET_MESSAGE(mesg, LZHAM_COMP_STATUS_OUTPUT_BUF_TOO_SMALL);
|
43
|
+
default:
|
44
|
+
mesg = "unknown code";
|
45
|
+
break;
|
46
|
+
}
|
47
|
+
|
48
|
+
rb_raise(eError,
|
49
|
+
"LZHAM encode error - %s (0x%04X)",
|
50
|
+
mesg, status);
|
51
|
+
}
|
52
|
+
|
53
|
+
static inline void
|
54
|
+
aux_decode_error(lzham_decompress_status_t status)
|
55
|
+
{
|
56
|
+
const char *mesg;
|
57
|
+
switch (status) {
|
58
|
+
SET_MESSAGE(mesg, LZHAM_DECOMP_STATUS_NOT_FINISHED);
|
59
|
+
SET_MESSAGE(mesg, LZHAM_DECOMP_STATUS_HAS_MORE_OUTPUT);
|
60
|
+
SET_MESSAGE(mesg, LZHAM_DECOMP_STATUS_NEEDS_MORE_INPUT);
|
61
|
+
SET_MESSAGE(mesg, LZHAM_DECOMP_STATUS_FIRST_SUCCESS_OR_FAILURE_CODE);
|
62
|
+
SET_MESSAGE(mesg, LZHAM_DECOMP_STATUS_FIRST_FAILURE_CODE);
|
63
|
+
SET_MESSAGE(mesg, LZHAM_DECOMP_STATUS_FAILED_DEST_BUF_TOO_SMALL);
|
64
|
+
SET_MESSAGE(mesg, LZHAM_DECOMP_STATUS_FAILED_EXPECTED_MORE_RAW_BYTES);
|
65
|
+
SET_MESSAGE(mesg, LZHAM_DECOMP_STATUS_FAILED_BAD_CODE);
|
66
|
+
SET_MESSAGE(mesg, LZHAM_DECOMP_STATUS_FAILED_ADLER32);
|
67
|
+
SET_MESSAGE(mesg, LZHAM_DECOMP_STATUS_FAILED_BAD_RAW_BLOCK);
|
68
|
+
SET_MESSAGE(mesg, LZHAM_DECOMP_STATUS_FAILED_BAD_COMP_BLOCK_SYNC_CHECK);
|
69
|
+
SET_MESSAGE(mesg, LZHAM_DECOMP_STATUS_FAILED_BAD_ZLIB_HEADER);
|
70
|
+
SET_MESSAGE(mesg, LZHAM_DECOMP_STATUS_FAILED_NEED_SEED_BYTES);
|
71
|
+
SET_MESSAGE(mesg, LZHAM_DECOMP_STATUS_FAILED_BAD_SEED_BYTES);
|
72
|
+
SET_MESSAGE(mesg, LZHAM_DECOMP_STATUS_FAILED_BAD_SYNC_BLOCK);
|
73
|
+
SET_MESSAGE(mesg, LZHAM_DECOMP_STATUS_INVALID_PARAMETER);
|
74
|
+
default:
|
75
|
+
mesg = "unknown code";
|
76
|
+
break;
|
77
|
+
}
|
78
|
+
|
79
|
+
rb_raise(eError,
|
80
|
+
"LZHAM decode error - %s (0x%04X)",
|
81
|
+
mesg, status);
|
82
|
+
}
|
83
|
+
|
84
|
+
static inline uint32_t
|
85
|
+
aux_hash_lookup_to_u32(VALUE hash, ID key, uint32_t defaultvalue)
|
86
|
+
{
|
87
|
+
VALUE d = rb_hash_lookup2(hash, ID2SYM(key), Qundef);
|
88
|
+
if (d == Qundef) { return defaultvalue; }
|
89
|
+
return NUM2UINT(d);
|
90
|
+
}
|
91
|
+
|
92
|
+
static inline lzham_compress_params
|
93
|
+
aux_conv_encode_params(VALUE opts)
|
94
|
+
{
|
95
|
+
lzham_compress_params p;
|
96
|
+
memset(&p, 0, sizeof(p));
|
97
|
+
p.m_struct_size = sizeof(p);
|
98
|
+
if (NIL_P(opts)) {
|
99
|
+
p.m_dict_size_log2 = LZHAM_MIN_DICT_SIZE_LOG2;
|
100
|
+
p.m_level = LZHAM_COMP_LEVEL_DEFAULT;
|
101
|
+
p.m_table_update_rate = 0;
|
102
|
+
p.m_max_helper_threads = -1;
|
103
|
+
p.m_compress_flags = 0; // (see lzham_compress_flags enum)
|
104
|
+
p.m_num_seed_bytes = 0;
|
105
|
+
p.m_pSeed_bytes = NULL;
|
106
|
+
p.m_table_max_update_interval = 0;
|
107
|
+
p.m_table_update_interval_slow_rate = 0;
|
108
|
+
} else {
|
109
|
+
p.m_dict_size_log2 = aux_hash_lookup_to_u32(opts, IDdictsize, LZHAM_MIN_DICT_SIZE_LOG2);
|
110
|
+
p.m_level = aux_hash_lookup_to_u32(opts, IDlevel, LZHAM_COMP_LEVEL_DEFAULT);
|
111
|
+
p.m_table_update_rate = aux_hash_lookup_to_u32(opts, IDtable_update_rate, 0);
|
112
|
+
p.m_max_helper_threads = aux_hash_lookup_to_u32(opts, IDthreads, -1);
|
113
|
+
p.m_compress_flags = aux_hash_lookup_to_u32(opts, IDflags, 0);
|
114
|
+
p.m_num_seed_bytes = 0;
|
115
|
+
p.m_pSeed_bytes = NULL;
|
116
|
+
p.m_table_max_update_interval = aux_hash_lookup_to_u32(opts, IDtable_max_update_interval, 0);
|
117
|
+
p.m_table_update_interval_slow_rate = aux_hash_lookup_to_u32(opts, IDtable_update_interval_slow_rate, 0);
|
118
|
+
}
|
119
|
+
return p;
|
120
|
+
}
|
121
|
+
|
122
|
+
/*
|
123
|
+
* call-seq:
|
124
|
+
* encode(string, opts = {}) -> encoded string
|
125
|
+
*/
|
126
|
+
static VALUE
|
127
|
+
ext_s_encode(int argc, VALUE argv[], VALUE mod)
|
128
|
+
{
|
129
|
+
VALUE src, opts;
|
130
|
+
rb_scan_args(argc, argv, "1:", &src, &opts);
|
131
|
+
rb_check_type(src, RUBY_T_STRING);
|
132
|
+
rb_str_locktmp(src);
|
133
|
+
size_t srcsize = RSTRING_LEN(src);
|
134
|
+
size_t destsize = lzham_z_compressBound(srcsize);
|
135
|
+
VALUE dest = rb_str_buf_new(destsize);
|
136
|
+
lzham_compress_params params = aux_conv_encode_params(opts);
|
137
|
+
lzham_compress_status_t s;
|
138
|
+
s = lzham_compress_memory(¶ms,
|
139
|
+
(lzham_uint8 *)RSTRING_PTR(dest), &destsize,
|
140
|
+
(lzham_uint8 *)RSTRING_PTR(src), srcsize, NULL);
|
141
|
+
|
142
|
+
rb_str_unlocktmp(src);
|
143
|
+
|
144
|
+
if (s != LZHAM_COMP_STATUS_SUCCESS) {
|
145
|
+
rb_str_resize(dest, 0);
|
146
|
+
aux_encode_error(s);
|
147
|
+
}
|
148
|
+
|
149
|
+
rb_str_resize(dest, destsize);
|
150
|
+
rb_str_set_len(dest, destsize);
|
151
|
+
|
152
|
+
return dest;
|
153
|
+
}
|
154
|
+
|
155
|
+
struct encoder
|
156
|
+
{
|
157
|
+
lzham_compress_state_ptr encoder;
|
158
|
+
VALUE outport;
|
159
|
+
VALUE outbuf;
|
160
|
+
};
|
161
|
+
|
162
|
+
static void
|
163
|
+
ext_enc_mark(struct encoder *p)
|
164
|
+
{
|
165
|
+
if (p) {
|
166
|
+
rb_gc_mark(p->outport);
|
167
|
+
rb_gc_mark(p->outbuf);
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
static void
|
172
|
+
ext_enc_free(struct encoder *p)
|
173
|
+
{
|
174
|
+
if (p) {
|
175
|
+
if (p->encoder) {
|
176
|
+
lzham_compress_deinit(p->encoder);
|
177
|
+
}
|
178
|
+
}
|
179
|
+
}
|
180
|
+
|
181
|
+
static VALUE
|
182
|
+
ext_enc_alloc(VALUE klass)
|
183
|
+
{
|
184
|
+
struct encoder *p;
|
185
|
+
VALUE obj = Data_Make_Struct(klass, struct encoder, ext_enc_mark, ext_enc_free, p);
|
186
|
+
return obj;
|
187
|
+
}
|
188
|
+
|
189
|
+
static inline struct encoder *
|
190
|
+
aux_encoder_refp(VALUE obj)
|
191
|
+
{
|
192
|
+
struct encoder *p;
|
193
|
+
Data_Get_Struct(obj, struct encoder, p);
|
194
|
+
return p;
|
195
|
+
}
|
196
|
+
|
197
|
+
static inline struct encoder *
|
198
|
+
aux_encoder_ref(VALUE obj)
|
199
|
+
{
|
200
|
+
struct encoder *p = aux_encoder_refp(obj);
|
201
|
+
if (!p || !p->encoder) {
|
202
|
+
rb_raise(eError,
|
203
|
+
"not initialized - #<%s:%p>",
|
204
|
+
rb_obj_classname(obj), (void *)obj);
|
205
|
+
}
|
206
|
+
return p;
|
207
|
+
}
|
208
|
+
|
209
|
+
/*
|
210
|
+
* call-seq:
|
211
|
+
* initialize(outport, opts = {})
|
212
|
+
*/
|
213
|
+
static VALUE
|
214
|
+
ext_enc_init(int argc, VALUE argv[], VALUE enc)
|
215
|
+
{
|
216
|
+
struct encoder *p = DATA_PTR(enc);
|
217
|
+
if (p->encoder) {
|
218
|
+
rb_raise(eError,
|
219
|
+
"already initialized - #<%s:%p>",
|
220
|
+
rb_obj_classname(enc), (void *)enc);
|
221
|
+
}
|
222
|
+
|
223
|
+
VALUE outport, opts;
|
224
|
+
rb_scan_args(argc, argv, "1:", &outport, &opts);
|
225
|
+
lzham_compress_params params = aux_conv_encode_params(opts);
|
226
|
+
p->encoder = lzham_compress_init(¶ms);
|
227
|
+
if (!p->encoder) {
|
228
|
+
rb_raise(eError,
|
229
|
+
"failed lzham_compress_init - #<%s:%p>",
|
230
|
+
rb_obj_classname(enc), (void *)enc);
|
231
|
+
}
|
232
|
+
|
233
|
+
p->outbuf = rb_str_buf_new(WORKBUF_SIZE);
|
234
|
+
p->outport = outport;
|
235
|
+
|
236
|
+
return enc;
|
237
|
+
}
|
238
|
+
|
239
|
+
struct enc_update_args
|
240
|
+
{
|
241
|
+
VALUE encoder;
|
242
|
+
VALUE src;
|
243
|
+
int flush;
|
244
|
+
};
|
245
|
+
|
246
|
+
struct aux_lzham_compress2_nogvl
|
247
|
+
{
|
248
|
+
lzham_compress_state_ptr state;
|
249
|
+
const lzham_uint8 *inbuf;
|
250
|
+
size_t *insize;
|
251
|
+
lzham_uint8 *outbuf;
|
252
|
+
size_t *outsize;
|
253
|
+
lzham_flush_t flush;
|
254
|
+
};
|
255
|
+
|
256
|
+
static void *
|
257
|
+
aux_lzham_compress2_nogvl(void *px)
|
258
|
+
{
|
259
|
+
struct aux_lzham_compress2_nogvl *p = px;
|
260
|
+
return (void *)lzham_compress2(p->state,
|
261
|
+
p->inbuf, p->insize, p->outbuf, p->outsize, p->flush);
|
262
|
+
}
|
263
|
+
|
264
|
+
static inline lzham_compress_status_t
|
265
|
+
aux_lzham_compress2(lzham_compress_state_ptr state,
|
266
|
+
const lzham_uint8 *inbuf, size_t *insize,
|
267
|
+
lzham_uint8 *outbuf, size_t *outsize,
|
268
|
+
lzham_flush_t flush)
|
269
|
+
{
|
270
|
+
struct aux_lzham_compress2_nogvl p = {
|
271
|
+
.state = state,
|
272
|
+
.inbuf = inbuf,
|
273
|
+
.insize = insize,
|
274
|
+
.outbuf = outbuf,
|
275
|
+
.outsize = outsize,
|
276
|
+
.flush = flush,
|
277
|
+
};
|
278
|
+
|
279
|
+
return (lzham_compress_status_t)rb_thread_call_without_gvl(aux_lzham_compress2_nogvl, &p, 0, 0);
|
280
|
+
}
|
281
|
+
|
282
|
+
static VALUE
|
283
|
+
enc_update_protected(struct enc_update_args *args)
|
284
|
+
{
|
285
|
+
struct encoder *p = aux_encoder_ref(args->encoder);
|
286
|
+
const char *inbuf, *intail;
|
287
|
+
|
288
|
+
if (NIL_P(args->src)) {
|
289
|
+
inbuf = NULL;
|
290
|
+
intail = NULL;
|
291
|
+
} else {
|
292
|
+
inbuf = RSTRING_PTR(args->src);
|
293
|
+
intail = inbuf + RSTRING_LEN(args->src);
|
294
|
+
}
|
295
|
+
|
296
|
+
for (;;) {
|
297
|
+
size_t insize = intail - inbuf;
|
298
|
+
rb_str_locktmp(p->outbuf);
|
299
|
+
size_t outsize = rb_str_capacity(p->outbuf);
|
300
|
+
lzham_compress_status_t s;
|
301
|
+
s = aux_lzham_compress2(p->encoder,
|
302
|
+
(lzham_uint8 *)inbuf, &insize,
|
303
|
+
(lzham_uint8 *)RSTRING_PTR(p->outbuf), &outsize, args->flush);
|
304
|
+
rb_str_unlocktmp(p->outbuf);
|
305
|
+
if (!NIL_P(args->src)) {
|
306
|
+
inbuf += insize;
|
307
|
+
if (inbuf == intail) {
|
308
|
+
inbuf = intail = NULL;
|
309
|
+
}
|
310
|
+
}
|
311
|
+
//fprintf(stderr, "%s:%d:%s: status=%d, insize=%zu, outsize=%zu\n", __FILE__, __LINE__, __func__, s, insize, outsize);
|
312
|
+
if (s != LZHAM_COMP_STATUS_SUCCESS &&
|
313
|
+
s != LZHAM_COMP_STATUS_NEEDS_MORE_INPUT &&
|
314
|
+
s != LZHAM_COMP_STATUS_NOT_FINISHED &&
|
315
|
+
s != LZHAM_COMP_STATUS_HAS_MORE_OUTPUT) {
|
316
|
+
|
317
|
+
aux_encode_error(s);
|
318
|
+
}
|
319
|
+
if (outsize > 0) {
|
320
|
+
rb_str_set_len(p->outbuf, outsize);
|
321
|
+
rb_funcall2(p->outport, ID_op_lshift, 1, &p->outbuf);
|
322
|
+
}
|
323
|
+
if (s != LZHAM_COMP_STATUS_HAS_MORE_OUTPUT) {
|
324
|
+
break;
|
325
|
+
}
|
326
|
+
}
|
327
|
+
|
328
|
+
return 0;
|
329
|
+
}
|
330
|
+
|
331
|
+
static inline void
|
332
|
+
enc_update(VALUE enc, VALUE src, int flush)
|
333
|
+
{
|
334
|
+
struct enc_update_args args = { enc, src, flush };
|
335
|
+
if (NIL_P(src)) {
|
336
|
+
enc_update_protected(&args);
|
337
|
+
} else {
|
338
|
+
rb_str_locktmp(src);
|
339
|
+
int state;
|
340
|
+
rb_protect((VALUE (*)(VALUE))enc_update_protected, (VALUE)&args, &state);
|
341
|
+
rb_str_unlocktmp(src);
|
342
|
+
if (state) {
|
343
|
+
rb_jump_tag(state);
|
344
|
+
}
|
345
|
+
}
|
346
|
+
}
|
347
|
+
|
348
|
+
/*
|
349
|
+
* call-seq:
|
350
|
+
* update(src, flush = LZHAM::NO_FLUSH) -> self
|
351
|
+
*/
|
352
|
+
static VALUE
|
353
|
+
ext_enc_update(int argc, VALUE argv[], VALUE enc)
|
354
|
+
{
|
355
|
+
VALUE src, flush;
|
356
|
+
rb_scan_args(argc, argv, "11", &src, &flush);
|
357
|
+
rb_check_type(src, RUBY_T_STRING);
|
358
|
+
if (NIL_P(flush)) {
|
359
|
+
enc_update(enc, src, 0);
|
360
|
+
} else {
|
361
|
+
enc_update(enc, src, NUM2INT(flush));
|
362
|
+
}
|
363
|
+
return enc;
|
364
|
+
}
|
365
|
+
|
366
|
+
static VALUE
|
367
|
+
ext_enc_finish(VALUE enc)
|
368
|
+
{
|
369
|
+
enc_update(enc, Qnil, LZHAM_FINISH);
|
370
|
+
return enc;
|
371
|
+
}
|
372
|
+
|
373
|
+
/*
|
374
|
+
* same as <tt>enc.update(src)</tt>
|
375
|
+
*/
|
376
|
+
static VALUE
|
377
|
+
ext_enc_op_lshift(VALUE enc, VALUE src)
|
378
|
+
{
|
379
|
+
rb_check_type(src, RUBY_T_STRING);
|
380
|
+
enc_update(enc, src, 0);
|
381
|
+
return enc;
|
382
|
+
}
|
383
|
+
|
384
|
+
/*
|
385
|
+
* decoder
|
386
|
+
*/
|
387
|
+
|
388
|
+
static inline lzham_decompress_params
|
389
|
+
aux_conv_decode_params(VALUE opts)
|
390
|
+
{
|
391
|
+
lzham_decompress_params p;
|
392
|
+
memset(&p, 0, sizeof(p));
|
393
|
+
p.m_struct_size = sizeof(p);
|
394
|
+
if (NIL_P(opts)) {
|
395
|
+
p.m_dict_size_log2 = LZHAM_MIN_DICT_SIZE_LOG2;
|
396
|
+
p.m_table_update_rate = 0;
|
397
|
+
p.m_decompress_flags = 0; // (see lzham_decompress_flags enum)
|
398
|
+
p.m_num_seed_bytes = 0;
|
399
|
+
p.m_pSeed_bytes = NULL;
|
400
|
+
p.m_table_max_update_interval = 0;
|
401
|
+
p.m_table_update_interval_slow_rate = 0;
|
402
|
+
} else {
|
403
|
+
p.m_dict_size_log2 = aux_hash_lookup_to_u32(opts, IDdictsize, LZHAM_MIN_DICT_SIZE_LOG2);
|
404
|
+
p.m_table_update_rate = aux_hash_lookup_to_u32(opts, IDtable_update_rate, 0);
|
405
|
+
p.m_decompress_flags = aux_hash_lookup_to_u32(opts, IDflags, 0);
|
406
|
+
p.m_num_seed_bytes = 0;
|
407
|
+
p.m_pSeed_bytes = NULL;
|
408
|
+
p.m_table_max_update_interval = aux_hash_lookup_to_u32(opts, IDtable_max_update_interval, 0);
|
409
|
+
p.m_table_update_interval_slow_rate = aux_hash_lookup_to_u32(opts, IDtable_update_interval_slow_rate, 0);
|
410
|
+
}
|
411
|
+
|
412
|
+
return p;
|
413
|
+
}
|
414
|
+
|
415
|
+
/*
|
416
|
+
* call-seq:
|
417
|
+
* decode(string, max_decoded_size, opts = {}) -> decoded string
|
418
|
+
*/
|
419
|
+
static VALUE
|
420
|
+
ext_s_decode(int argc, VALUE argv[], VALUE mod)
|
421
|
+
{
|
422
|
+
VALUE src, size, opts;
|
423
|
+
rb_scan_args(argc, argv, "2:", &src, &size, &opts);
|
424
|
+
rb_check_type(src, RUBY_T_STRING);
|
425
|
+
rb_str_locktmp(src);
|
426
|
+
size_t srcsize = RSTRING_LEN(src);
|
427
|
+
size_t destsize = NUM2SIZET(size);
|
428
|
+
VALUE dest = rb_str_buf_new(destsize);
|
429
|
+
lzham_decompress_params p = aux_conv_decode_params(opts);
|
430
|
+
lzham_decompress_status_t s;
|
431
|
+
s = lzham_decompress_memory(&p,
|
432
|
+
(lzham_uint8 *)RSTRING_PTR(dest), &destsize,
|
433
|
+
(lzham_uint8 *)RSTRING_PTR(src), srcsize, NULL);
|
434
|
+
|
435
|
+
rb_str_unlocktmp(src);
|
436
|
+
|
437
|
+
if (s != LZHAM_DECOMP_STATUS_SUCCESS) {
|
438
|
+
rb_str_resize(dest, 0);
|
439
|
+
aux_decode_error(s);
|
440
|
+
}
|
441
|
+
|
442
|
+
rb_str_resize(dest, destsize);
|
443
|
+
rb_str_set_len(dest, destsize);
|
444
|
+
|
445
|
+
return dest;
|
446
|
+
}
|
447
|
+
|
448
|
+
struct decoder
|
449
|
+
{
|
450
|
+
lzham_decompress_state_ptr decoder;
|
451
|
+
VALUE outport;
|
452
|
+
VALUE outbuf;
|
453
|
+
};
|
454
|
+
|
455
|
+
static void
|
456
|
+
ext_dec_mark(struct decoder *p)
|
457
|
+
{
|
458
|
+
if (p) {
|
459
|
+
rb_gc_mark(p->outport);
|
460
|
+
rb_gc_mark(p->outbuf);
|
461
|
+
}
|
462
|
+
}
|
463
|
+
|
464
|
+
static void
|
465
|
+
ext_dec_free(struct decoder *p)
|
466
|
+
{
|
467
|
+
if (p) {
|
468
|
+
if (p->decoder) {
|
469
|
+
lzham_decompress_deinit(p->decoder);
|
470
|
+
}
|
471
|
+
}
|
472
|
+
}
|
473
|
+
|
474
|
+
static VALUE
|
475
|
+
ext_dec_alloc(VALUE klass)
|
476
|
+
{
|
477
|
+
struct decoder *p;
|
478
|
+
VALUE obj = Data_Make_Struct(klass, struct decoder, ext_dec_mark, ext_dec_free, p);
|
479
|
+
return obj;
|
480
|
+
}
|
481
|
+
|
482
|
+
static inline struct decoder *
|
483
|
+
aux_decoder_refp(VALUE obj)
|
484
|
+
{
|
485
|
+
struct decoder *p;
|
486
|
+
Data_Get_Struct(obj, struct decoder, p);
|
487
|
+
return p;
|
488
|
+
}
|
489
|
+
|
490
|
+
static inline struct decoder *
|
491
|
+
aux_decoder_ref(VALUE obj)
|
492
|
+
{
|
493
|
+
struct decoder *p = aux_decoder_refp(obj);
|
494
|
+
if (!p || !p->decoder) {
|
495
|
+
rb_raise(eError,
|
496
|
+
"not initialized - #<%s:%p>",
|
497
|
+
rb_obj_classname(obj), (void *)obj);
|
498
|
+
}
|
499
|
+
return p;
|
500
|
+
}
|
501
|
+
|
502
|
+
static VALUE
|
503
|
+
ext_dec_init(int argc, VALUE argv[], VALUE dec)
|
504
|
+
{
|
505
|
+
struct decoder *p = DATA_PTR(dec);
|
506
|
+
if (p->decoder) {
|
507
|
+
rb_raise(eError,
|
508
|
+
"already initialized - #<%s:%p>",
|
509
|
+
rb_obj_classname(dec), (void *)dec);
|
510
|
+
}
|
511
|
+
|
512
|
+
VALUE outport, opts;
|
513
|
+
rb_scan_args(argc, argv, "1:", &outport, &opts);
|
514
|
+
lzham_decompress_params params = aux_conv_decode_params(opts);
|
515
|
+
p->decoder = lzham_decompress_init(¶ms);
|
516
|
+
if (!p->decoder) {
|
517
|
+
rb_raise(eError,
|
518
|
+
"failed lzham_decompress_init - #<%s:%p>",
|
519
|
+
rb_obj_classname(dec), (void *)dec);
|
520
|
+
}
|
521
|
+
|
522
|
+
p->outbuf = rb_str_buf_new(WORKBUF_SIZE);
|
523
|
+
p->outport = outport;
|
524
|
+
|
525
|
+
return dec;
|
526
|
+
}
|
527
|
+
|
528
|
+
struct aux_lzham_decompress_nogvl
|
529
|
+
{
|
530
|
+
lzham_decompress_state_ptr state;
|
531
|
+
const lzham_uint8 *inbuf;
|
532
|
+
size_t *insize;
|
533
|
+
lzham_uint8 *outbuf;
|
534
|
+
size_t *outsize;
|
535
|
+
lzham_bool flags;
|
536
|
+
};
|
537
|
+
|
538
|
+
static void *
|
539
|
+
aux_lzham_decompress_nogvl(void *px)
|
540
|
+
{
|
541
|
+
struct aux_lzham_decompress_nogvl *p = px;
|
542
|
+
return (void *)lzham_decompress(p->state, p->inbuf, p->insize, p->outbuf, p->outsize, p->flags);
|
543
|
+
}
|
544
|
+
|
545
|
+
static inline lzham_decompress_status_t
|
546
|
+
aux_lzham_decompress(lzham_decompress_state_ptr state,
|
547
|
+
const lzham_uint8 *inbuf, size_t *insize,
|
548
|
+
lzham_uint8 *outbuf, size_t *outsize,
|
549
|
+
lzham_bool flags)
|
550
|
+
{
|
551
|
+
struct aux_lzham_decompress_nogvl p = {
|
552
|
+
.state = state,
|
553
|
+
.inbuf = inbuf,
|
554
|
+
.insize = insize,
|
555
|
+
.outbuf = outbuf,
|
556
|
+
.outsize = outsize,
|
557
|
+
.flags = flags,
|
558
|
+
};
|
559
|
+
|
560
|
+
return (lzham_decompress_status_t)rb_thread_call_without_gvl(aux_lzham_decompress_nogvl, &p, 0, 0);
|
561
|
+
}
|
562
|
+
|
563
|
+
struct dec_update_args
|
564
|
+
{
|
565
|
+
VALUE decoder;
|
566
|
+
VALUE src;
|
567
|
+
int flush;
|
568
|
+
};
|
569
|
+
|
570
|
+
static VALUE
|
571
|
+
dec_update_protected(struct dec_update_args *args)
|
572
|
+
{
|
573
|
+
struct decoder *p = aux_decoder_ref(args->decoder);
|
574
|
+
const char *inbuf, *intail;
|
575
|
+
|
576
|
+
if (NIL_P(args->src)) {
|
577
|
+
inbuf = NULL;
|
578
|
+
intail = NULL;
|
579
|
+
} else {
|
580
|
+
inbuf = RSTRING_PTR(args->src);
|
581
|
+
intail = inbuf + RSTRING_LEN(args->src);
|
582
|
+
}
|
583
|
+
|
584
|
+
for (;;) {
|
585
|
+
size_t insize = intail - inbuf;
|
586
|
+
rb_str_locktmp(p->outbuf);
|
587
|
+
size_t outsize = rb_str_capacity(p->outbuf);
|
588
|
+
lzham_decompress_status_t s;
|
589
|
+
//fprintf(stderr, "%s:%d:%s: inbuf=%p, insize=%zu, outbuf=%p, outsize=%zu\n", __FILE__, __LINE__, __func__, inbuf, insize, RSTRING_PTR(p->outbuf), outsize);
|
590
|
+
s = aux_lzham_decompress(p->decoder,
|
591
|
+
(lzham_uint8 *)inbuf, &insize,
|
592
|
+
(lzham_uint8 *)RSTRING_PTR(p->outbuf), &outsize, args->flush);
|
593
|
+
rb_str_unlocktmp(p->outbuf);
|
594
|
+
//fprintf(stderr, "%s:%d:%s: status=%d, insize=%zu, outsize=%zu\n", __FILE__, __LINE__, __func__, s, insize, outsize);
|
595
|
+
if (!NIL_P(args->src)) {
|
596
|
+
inbuf += insize;
|
597
|
+
}
|
598
|
+
if (s != LZHAM_DECOMP_STATUS_NOT_FINISHED &&
|
599
|
+
s != LZHAM_DECOMP_STATUS_HAS_MORE_OUTPUT &&
|
600
|
+
s != LZHAM_DECOMP_STATUS_NEEDS_MORE_INPUT &&
|
601
|
+
s != LZHAM_DECOMP_STATUS_SUCCESS) {
|
602
|
+
|
603
|
+
aux_decode_error(s);
|
604
|
+
}
|
605
|
+
if (outsize > 0) {
|
606
|
+
rb_str_set_len(p->outbuf, outsize);
|
607
|
+
rb_funcall2(p->outport, ID_op_lshift, 1, &p->outbuf);
|
608
|
+
}
|
609
|
+
if (s != LZHAM_DECOMP_STATUS_NOT_FINISHED) {
|
610
|
+
break;
|
611
|
+
}
|
612
|
+
}
|
613
|
+
|
614
|
+
return 0;
|
615
|
+
}
|
616
|
+
|
617
|
+
static inline void
|
618
|
+
dec_update(VALUE dec, VALUE src, int flush)
|
619
|
+
{
|
620
|
+
struct dec_update_args args = { dec, src, flush };
|
621
|
+
if (NIL_P(src)) {
|
622
|
+
dec_update_protected(&args);
|
623
|
+
} else {
|
624
|
+
rb_str_locktmp(src);
|
625
|
+
int state;
|
626
|
+
rb_protect((VALUE (*)(VALUE))dec_update_protected, (VALUE)&args, &state);
|
627
|
+
rb_str_unlocktmp(src);
|
628
|
+
if (state) {
|
629
|
+
rb_jump_tag(state);
|
630
|
+
}
|
631
|
+
}
|
632
|
+
}
|
633
|
+
|
634
|
+
/*
|
635
|
+
* call-seq:
|
636
|
+
* update(src, flush = false) -> self
|
637
|
+
*/
|
638
|
+
static VALUE
|
639
|
+
ext_dec_update(int argc, VALUE argv[], VALUE dec)
|
640
|
+
{
|
641
|
+
VALUE src, flush;
|
642
|
+
rb_scan_args(argc, argv, "11", &src, &flush);
|
643
|
+
rb_check_type(src, RUBY_T_STRING);
|
644
|
+
dec_update(dec, src, RTEST(flush) ? 1 : 0);
|
645
|
+
return dec;
|
646
|
+
}
|
647
|
+
|
648
|
+
static VALUE
|
649
|
+
ext_dec_finish(VALUE dec)
|
650
|
+
{
|
651
|
+
dec_update(dec, Qnil, 1);
|
652
|
+
return dec;
|
653
|
+
}
|
654
|
+
|
655
|
+
static VALUE
|
656
|
+
ext_dec_op_lshift(VALUE dec, VALUE src)
|
657
|
+
{
|
658
|
+
rb_check_type(src, RUBY_T_STRING);
|
659
|
+
dec_update(dec, src, 0);
|
660
|
+
return dec;
|
661
|
+
}
|
662
|
+
|
663
|
+
void
|
664
|
+
Init_extlzham(void)
|
665
|
+
{
|
666
|
+
ID_op_lshift = rb_intern("<<");
|
667
|
+
IDdictsize = rb_intern("dictsize");
|
668
|
+
IDlevel = rb_intern("level");
|
669
|
+
IDtable_update_rate = rb_intern("table_update_rate");
|
670
|
+
IDthreads = rb_intern("threads");
|
671
|
+
IDflags = rb_intern("flags");
|
672
|
+
IDtable_max_update_interval = rb_intern("table_max_update_interval");
|
673
|
+
IDtable_update_interval_slow_rate = rb_intern("table_update_interval_slow_rate");
|
674
|
+
|
675
|
+
mLZHAM = rb_define_module("LZHAM");
|
676
|
+
rb_define_const(mLZHAM, "LZHAM", mLZHAM);
|
677
|
+
rb_define_const(mLZHAM, "LIBVERSION", UINT2NUM(lzham_get_version()));
|
678
|
+
|
679
|
+
mConsts = rb_define_module_under(mLZHAM, "Constants");
|
680
|
+
rb_include_module(mLZHAM, mConsts);
|
681
|
+
rb_define_const(mConsts, "NO_FLUSH", INT2FIX(LZHAM_NO_FLUSH));
|
682
|
+
rb_define_const(mConsts, "SYNC_FLUSH", INT2FIX(LZHAM_SYNC_FLUSH));
|
683
|
+
rb_define_const(mConsts, "FULL_FLUSH", INT2FIX(LZHAM_FULL_FLUSH));
|
684
|
+
rb_define_const(mConsts, "FINISH", INT2FIX(LZHAM_FINISH));
|
685
|
+
rb_define_const(mConsts, "TABLE_FLUSH", INT2FIX(LZHAM_TABLE_FLUSH));
|
686
|
+
rb_define_const(mConsts, "MIN_DICT_SIZE_LOG2", INT2FIX(LZHAM_MIN_DICT_SIZE_LOG2));
|
687
|
+
rb_define_const(mConsts, "MAX_DICT_SIZE_LOG2_X86", INT2FIX(LZHAM_MAX_DICT_SIZE_LOG2_X86));
|
688
|
+
rb_define_const(mConsts, "MAX_DICT_SIZE_LOG2_X64", INT2FIX(LZHAM_MAX_DICT_SIZE_LOG2_X64));
|
689
|
+
rb_define_const(mConsts, "MAX_HELPER_THREADS", INT2FIX(LZHAM_MAX_HELPER_THREADS));
|
690
|
+
rb_define_const(mConsts, "COMP_FLAG_EXTREME_PARSING", INT2FIX(LZHAM_COMP_FLAG_EXTREME_PARSING));
|
691
|
+
rb_define_const(mConsts, "COMP_FLAG_DETERMINISTIC_PARSING", INT2FIX(LZHAM_COMP_FLAG_DETERMINISTIC_PARSING));
|
692
|
+
rb_define_const(mConsts, "COMP_FLAG_TRADEOFF_DECOMPRESSION_RATE_FOR_COMP_RATIO", INT2FIX(LZHAM_COMP_FLAG_TRADEOFF_DECOMPRESSION_RATE_FOR_COMP_RATIO));
|
693
|
+
rb_define_const(mConsts, "COMP_FLAG_WRITE_ZLIB_STREAM", INT2FIX(LZHAM_COMP_FLAG_WRITE_ZLIB_STREAM));
|
694
|
+
rb_define_const(mConsts, "INSANELY_SLOW_TABLE_UPDATE_RATE", INT2FIX(LZHAM_INSANELY_SLOW_TABLE_UPDATE_RATE));
|
695
|
+
rb_define_const(mConsts, "SLOWEST_TABLE_UPDATE_RATE", INT2FIX(LZHAM_SLOWEST_TABLE_UPDATE_RATE));
|
696
|
+
rb_define_const(mConsts, "DEFAULT_TABLE_UPDATE_RATE", INT2FIX(LZHAM_DEFAULT_TABLE_UPDATE_RATE));
|
697
|
+
rb_define_const(mConsts, "FASTEST_TABLE_UPDATE_RATE", INT2FIX(LZHAM_FASTEST_TABLE_UPDATE_RATE));
|
698
|
+
rb_define_const(mConsts, "DECOMP_FLAG_OUTPUT_UNBUFFERED", INT2FIX(LZHAM_DECOMP_FLAG_OUTPUT_UNBUFFERED));
|
699
|
+
rb_define_const(mConsts, "DECOMP_FLAG_COMPUTE_ADLER32", INT2FIX(LZHAM_DECOMP_FLAG_COMPUTE_ADLER32));
|
700
|
+
rb_define_const(mConsts, "DECOMP_FLAG_READ_ZLIB_STREAM", INT2FIX(LZHAM_DECOMP_FLAG_READ_ZLIB_STREAM));
|
701
|
+
rb_define_const(mConsts, "LZHAM_NO_FLUSH", INT2FIX(LZHAM_NO_FLUSH));
|
702
|
+
rb_define_const(mConsts, "LZHAM_SYNC_FLUSH", INT2FIX(LZHAM_SYNC_FLUSH));
|
703
|
+
rb_define_const(mConsts, "LZHAM_FULL_FLUSH", INT2FIX(LZHAM_FULL_FLUSH));
|
704
|
+
rb_define_const(mConsts, "LZHAM_FINISH", INT2FIX(LZHAM_FINISH));
|
705
|
+
rb_define_const(mConsts, "LZHAM_TABLE_FLUSH", INT2FIX(LZHAM_TABLE_FLUSH));
|
706
|
+
rb_define_const(mConsts, "LZHAM_MIN_DICT_SIZE_LOG2", INT2FIX(LZHAM_MIN_DICT_SIZE_LOG2));
|
707
|
+
rb_define_const(mConsts, "LZHAM_MAX_DICT_SIZE_LOG2_X86", INT2FIX(LZHAM_MAX_DICT_SIZE_LOG2_X86));
|
708
|
+
rb_define_const(mConsts, "LZHAM_MAX_DICT_SIZE_LOG2_X64", INT2FIX(LZHAM_MAX_DICT_SIZE_LOG2_X64));
|
709
|
+
rb_define_const(mConsts, "LZHAM_MAX_HELPER_THREADS", INT2FIX(LZHAM_MAX_HELPER_THREADS));
|
710
|
+
rb_define_const(mConsts, "LZHAM_COMP_FLAG_EXTREME_PARSING", INT2FIX(LZHAM_COMP_FLAG_EXTREME_PARSING));
|
711
|
+
rb_define_const(mConsts, "LZHAM_COMP_FLAG_DETERMINISTIC_PARSING", INT2FIX(LZHAM_COMP_FLAG_DETERMINISTIC_PARSING));
|
712
|
+
rb_define_const(mConsts, "LZHAM_COMP_FLAG_TRADEOFF_DECOMPRESSION_RATE_FOR_COMP_RATIO", INT2FIX(LZHAM_COMP_FLAG_TRADEOFF_DECOMPRESSION_RATE_FOR_COMP_RATIO));
|
713
|
+
rb_define_const(mConsts, "LZHAM_COMP_FLAG_WRITE_ZLIB_STREAM", INT2FIX(LZHAM_COMP_FLAG_WRITE_ZLIB_STREAM));
|
714
|
+
rb_define_const(mConsts, "LZHAM_INSANELY_SLOW_TABLE_UPDATE_RATE", INT2FIX(LZHAM_INSANELY_SLOW_TABLE_UPDATE_RATE));
|
715
|
+
rb_define_const(mConsts, "LZHAM_SLOWEST_TABLE_UPDATE_RATE", INT2FIX(LZHAM_SLOWEST_TABLE_UPDATE_RATE));
|
716
|
+
rb_define_const(mConsts, "LZHAM_DEFAULT_TABLE_UPDATE_RATE", INT2FIX(LZHAM_DEFAULT_TABLE_UPDATE_RATE));
|
717
|
+
rb_define_const(mConsts, "LZHAM_FASTEST_TABLE_UPDATE_RATE", INT2FIX(LZHAM_FASTEST_TABLE_UPDATE_RATE));
|
718
|
+
rb_define_const(mConsts, "LZHAM_DECOMP_FLAG_OUTPUT_UNBUFFERED", INT2FIX(LZHAM_DECOMP_FLAG_OUTPUT_UNBUFFERED));
|
719
|
+
rb_define_const(mConsts, "LZHAM_DECOMP_FLAG_COMPUTE_ADLER32", INT2FIX(LZHAM_DECOMP_FLAG_COMPUTE_ADLER32));
|
720
|
+
rb_define_const(mConsts, "LZHAM_DECOMP_FLAG_READ_ZLIB_STREAM", INT2FIX(LZHAM_DECOMP_FLAG_READ_ZLIB_STREAM));
|
721
|
+
|
722
|
+
cEncoder = rb_define_class_under(mLZHAM, "Encoder", rb_cObject);
|
723
|
+
rb_include_module(cEncoder, mConsts);
|
724
|
+
rb_define_alloc_func(cEncoder, ext_enc_alloc);
|
725
|
+
rb_define_singleton_method(cEncoder, "encode", RUBY_METHOD_FUNC(ext_s_encode), -1);
|
726
|
+
rb_define_method(cEncoder, "initialize", RUBY_METHOD_FUNC(ext_enc_init), -1);
|
727
|
+
rb_define_method(cEncoder, "update", RUBY_METHOD_FUNC(ext_enc_update), -1);
|
728
|
+
rb_define_method(cEncoder, "finish", RUBY_METHOD_FUNC(ext_enc_finish), 0);
|
729
|
+
rb_define_method(cEncoder, "<<", RUBY_METHOD_FUNC(ext_enc_op_lshift), 1);
|
730
|
+
|
731
|
+
cDecoder = rb_define_class_under(mLZHAM, "Decoder", rb_cObject);
|
732
|
+
rb_include_module(cDecoder, mConsts);
|
733
|
+
rb_define_alloc_func(cDecoder, ext_dec_alloc);
|
734
|
+
rb_define_singleton_method(cDecoder, "decode", RUBY_METHOD_FUNC(ext_s_decode), -1);
|
735
|
+
rb_define_method(cDecoder, "initialize", RUBY_METHOD_FUNC(ext_dec_init), -1);
|
736
|
+
rb_define_method(cDecoder, "update", RUBY_METHOD_FUNC(ext_dec_update), -1);
|
737
|
+
rb_define_method(cDecoder, "finish", RUBY_METHOD_FUNC(ext_dec_finish), 0);
|
738
|
+
rb_define_method(cDecoder, "<<", RUBY_METHOD_FUNC(ext_dec_op_lshift), 1);
|
739
|
+
|
740
|
+
eError = rb_define_class_under(mLZHAM, "Error", rb_eRuntimeError);
|
741
|
+
}
|