zstdlib 0.5.0-x64-mingw32 → 0.6.0-x64-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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 96ca25a2f2935534780679e291e8fcd7dbef97a47c0631dcf51414c6e6413336
4
- data.tar.gz: 937a6f5c4ec14c146dd3284f25db08b43915e7d776f4bde070eee5d19a8aede8
3
+ metadata.gz: 6ad50724d3c6b4f93dc41a647daf6814105615fe48b93c5892dc94fe0b702795
4
+ data.tar.gz: 5ee8ae3e1e8b7fad7dff7ca6ebb7932ed92f49334ef44717044f80990d07a5ca
5
5
  SHA512:
6
- metadata.gz: 495c5a0225f8ad8c3a21a497fb9460021803318792a401a6d38f8c8138c2cda8dcdfb7306992a24be9bad9ea9587f9125a76a0f993bbc56118337b5e84500a5a
7
- data.tar.gz: ae7b3c2ff162eb9419e8360bf40968d1d519d0d062cdc6bc2a6a4852274e035e240abae6e37a44934185b1251e7d2ec68073a8d081db6cd1f786e90ba16db715
6
+ metadata.gz: e025e14b58a3df5d6d5f9f7f1ee75b492bacac9003ab93972be8d754cfbd94943bcad27be3994550d7037eada6464500ec1f19ad05307c30ab871f191caff917
7
+ data.tar.gz: 75f835bc30134d20502eb21641db0eebd00d6aed9c7b278b1490d173b2e450fc84c5c6976f726c71848e200a32b56f926e88ddcf1399c870f19bffeae7d882c4
data/CHANGES.md CHANGED
@@ -1,3 +1,10 @@
1
+ # 0.6.0
2
+
3
+ Added support for MRI Ruby version `2.7`
4
+
5
+ Upgraded rake-compiler-dock to `1.0.0`
6
+
7
+
1
8
  # 0.5.0
2
9
 
3
10
  Zstd version update to `1.4.4`
@@ -9,7 +9,7 @@ include FileUtils
9
9
  ZSTD_VERSION = '1.4.4'
10
10
  ZLIB_VERSION = '1.2.11'
11
11
  RB_VERSION = CONFIG['MAJOR']+'.'+CONFIG['MINOR']
12
- ZMOD_VERSION = RB_VERSION >= '2.3' ? '2.6' : RB_VERSION # Review requirements with every new zlib module release!
12
+ ZMOD_VERSION = RB_VERSION >= '2.3' ? '2.7' : RB_VERSION # Review requirements with every new zlib module release!
13
13
 
14
14
  root = File.dirname(__FILE__)
15
15
 
@@ -0,0 +1,4895 @@
1
+ #include <zstd.h>
2
+ /*
3
+ * zlib.c - An interface for zlib.
4
+ *
5
+ * Copyright (C) UENO Katsuhiro 2000-2003
6
+ *
7
+ * $Id$
8
+ */
9
+
10
+ #include <ruby.h>
11
+ #include <zstd_zlibwrapper.h>
12
+ #include <time.h>
13
+ #include <ruby/io.h>
14
+ #include <ruby/thread.h>
15
+
16
+ #ifdef HAVE_VALGRIND_MEMCHECK_H
17
+ # include <valgrind/memcheck.h>
18
+ # ifndef VALGRIND_MAKE_MEM_DEFINED
19
+ # define VALGRIND_MAKE_MEM_DEFINED(p, n) VALGRIND_MAKE_READABLE((p), (n))
20
+ # endif
21
+ # ifndef VALGRIND_MAKE_MEM_UNDEFINED
22
+ # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) VALGRIND_MAKE_WRITABLE((p), (n))
23
+ # endif
24
+ #else
25
+ # define VALGRIND_MAKE_MEM_DEFINED(p, n) 0
26
+ # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0
27
+ #endif
28
+
29
+ #define RUBY_ZLIB_VERSION "1.1.0"
30
+
31
+ #ifndef RB_PASS_CALLED_KEYWORDS
32
+ # define rb_class_new_instance_kw(argc, argv, klass, kw_splat) rb_class_new_instance(argc, argv, klass)
33
+ #endif
34
+
35
+ #ifndef GZIP_SUPPORT
36
+ #define GZIP_SUPPORT 1
37
+ #endif
38
+
39
+ /* from zutil.h */
40
+ #ifndef DEF_MEM_LEVEL
41
+ #if MAX_MEM_LEVEL >= 8
42
+ #define DEF_MEM_LEVEL 8
43
+ #else
44
+ #define DEF_MEM_LEVEL MAX_MEM_LEVEL
45
+ #endif
46
+ #endif
47
+
48
+ #if SIZEOF_LONG > SIZEOF_INT
49
+ static inline uInt
50
+ max_uint(long n)
51
+ {
52
+ if (n > UINT_MAX) n = UINT_MAX;
53
+ return (uInt)n;
54
+ }
55
+ #define MAX_UINT(n) max_uint(n)
56
+ #else
57
+ #define MAX_UINT(n) (uInt)(n)
58
+ #endif
59
+
60
+ static ID id_dictionaries;
61
+
62
+ /*--------- Prototypes --------*/
63
+
64
+ static NORETURN(void raise_zlib_error(int, const char*));
65
+ static VALUE rb_zlib_version(VALUE);
66
+ static VALUE do_checksum(int, VALUE*, uLong (*)(uLong, const Bytef*, uInt));
67
+ static VALUE rb_zlib_adler32(int, VALUE*, VALUE);
68
+ static VALUE rb_zlib_crc32(int, VALUE*, VALUE);
69
+ static VALUE rb_zlib_crc_table(VALUE);
70
+ static voidpf zlib_mem_alloc(voidpf, uInt, uInt);
71
+ static void zlib_mem_free(voidpf, voidpf);
72
+ static void finalizer_warn(const char*);
73
+
74
+ struct zstream;
75
+ struct zstream_funcs;
76
+ struct zstream_run_args;
77
+ static void zstream_init(struct zstream*, const struct zstream_funcs*);
78
+ static void zstream_expand_buffer(struct zstream*);
79
+ static void zstream_expand_buffer_into(struct zstream*, unsigned long);
80
+ static int zstream_expand_buffer_non_stream(struct zstream *z);
81
+ static void zstream_append_buffer(struct zstream*, const Bytef*, long);
82
+ static VALUE zstream_detach_buffer(struct zstream*);
83
+ static VALUE zstream_shift_buffer(struct zstream*, long);
84
+ static void zstream_buffer_ungets(struct zstream*, const Bytef*, unsigned long);
85
+ static void zstream_buffer_ungetbyte(struct zstream*, int);
86
+ static void zstream_append_input(struct zstream*, const Bytef*, long);
87
+ static void zstream_discard_input(struct zstream*, long);
88
+ static void zstream_reset_input(struct zstream*);
89
+ static void zstream_passthrough_input(struct zstream*);
90
+ static VALUE zstream_detach_input(struct zstream*);
91
+ static void zstream_reset(struct zstream*);
92
+ static VALUE zstream_end(struct zstream*);
93
+ static VALUE zstream_ensure_end(VALUE v);
94
+ static void zstream_run(struct zstream*, Bytef*, long, int);
95
+ static VALUE zstream_sync(struct zstream*, Bytef*, long);
96
+ static void zstream_mark(void*);
97
+ static void zstream_free(void*);
98
+ static VALUE zstream_new(VALUE, const struct zstream_funcs*);
99
+ static struct zstream *get_zstream(VALUE);
100
+ static void zstream_finalize(struct zstream*);
101
+
102
+ static VALUE rb_zstream_end(VALUE);
103
+ static VALUE rb_zstream_reset(VALUE);
104
+ static VALUE rb_zstream_finish(VALUE);
105
+ static VALUE rb_zstream_flush_next_in(VALUE);
106
+ static VALUE rb_zstream_flush_next_out(VALUE);
107
+ static VALUE rb_zstream_avail_out(VALUE);
108
+ static VALUE rb_zstream_set_avail_out(VALUE, VALUE);
109
+ static VALUE rb_zstream_avail_in(VALUE);
110
+ static VALUE rb_zstream_total_in(VALUE);
111
+ static VALUE rb_zstream_total_out(VALUE);
112
+ static VALUE rb_zstream_data_type(VALUE);
113
+ static VALUE rb_zstream_adler(VALUE);
114
+ static VALUE rb_zstream_finished_p(VALUE);
115
+ static VALUE rb_zstream_closed_p(VALUE);
116
+
117
+ static VALUE rb_deflate_s_allocate(VALUE);
118
+ static VALUE rb_deflate_initialize(int, VALUE*, VALUE);
119
+ static VALUE rb_deflate_init_copy(VALUE, VALUE);
120
+ static VALUE deflate_run(VALUE);
121
+ static VALUE rb_deflate_s_deflate(int, VALUE*, VALUE);
122
+ static void do_deflate(struct zstream*, VALUE, int);
123
+ static VALUE rb_deflate_deflate(int, VALUE*, VALUE);
124
+ static VALUE rb_deflate_addstr(VALUE, VALUE);
125
+ static VALUE rb_deflate_flush(int, VALUE*, VALUE);
126
+ static VALUE rb_deflate_params(VALUE, VALUE, VALUE);
127
+ static VALUE rb_deflate_set_dictionary(VALUE, VALUE);
128
+
129
+ static VALUE inflate_run(VALUE);
130
+ static VALUE rb_inflate_s_allocate(VALUE);
131
+ static VALUE rb_inflate_initialize(int, VALUE*, VALUE);
132
+ static VALUE rb_inflate_s_inflate(VALUE, VALUE);
133
+ static void do_inflate(struct zstream*, VALUE);
134
+ static VALUE rb_inflate_inflate(VALUE, VALUE);
135
+ static VALUE rb_inflate_addstr(VALUE, VALUE);
136
+ static VALUE rb_inflate_sync(VALUE, VALUE);
137
+ static VALUE rb_inflate_sync_point_p(VALUE);
138
+ static VALUE rb_inflate_set_dictionary(VALUE, VALUE);
139
+
140
+ #if GZIP_SUPPORT
141
+ struct gzfile;
142
+ static void gzfile_mark(void*);
143
+ static void gzfile_free(void*);
144
+ static VALUE gzfile_new(VALUE, const struct zstream_funcs*, void (*) _((struct gzfile*)));
145
+ static void gzfile_reset(struct gzfile*);
146
+ static void gzfile_close(struct gzfile*, int);
147
+ static void gzfile_write_raw(struct gzfile*);
148
+ static VALUE gzfile_read_raw_partial(VALUE);
149
+ static VALUE gzfile_read_raw_rescue(VALUE,VALUE);
150
+ static VALUE gzfile_read_raw(struct gzfile*, VALUE outbuf);
151
+ static int gzfile_read_raw_ensure(struct gzfile*, long, VALUE outbuf);
152
+ static char *gzfile_read_raw_until_zero(struct gzfile*, long);
153
+ static unsigned int gzfile_get16(const unsigned char*);
154
+ static unsigned long gzfile_get32(const unsigned char*);
155
+ static void gzfile_set32(unsigned long n, unsigned char*);
156
+ static void gzfile_make_header(struct gzfile*);
157
+ static void gzfile_make_footer(struct gzfile*);
158
+ static void gzfile_read_header(struct gzfile*, VALUE outbuf);
159
+ static void gzfile_check_footer(struct gzfile*, VALUE outbuf);
160
+ static void gzfile_write(struct gzfile*, Bytef*, long);
161
+ static long gzfile_read_more(struct gzfile*, VALUE outbuf);
162
+ static void gzfile_calc_crc(struct gzfile*, VALUE);
163
+ static VALUE gzfile_read(struct gzfile*, long);
164
+ static VALUE gzfile_read_all(struct gzfile*);
165
+ static void gzfile_ungets(struct gzfile*, const Bytef*, long);
166
+ static void gzfile_ungetbyte(struct gzfile*, int);
167
+ static VALUE gzfile_writer_end_run(VALUE);
168
+ static void gzfile_writer_end(struct gzfile*);
169
+ static VALUE gzfile_reader_end_run(VALUE);
170
+ static void gzfile_reader_end(struct gzfile*);
171
+ static void gzfile_reader_rewind(struct gzfile*);
172
+ static VALUE gzfile_reader_get_unused(struct gzfile*);
173
+ static struct gzfile *get_gzfile(VALUE);
174
+ static VALUE gzfile_ensure_close(VALUE);
175
+ static VALUE rb_gzfile_s_wrap(int, VALUE*, VALUE);
176
+ static VALUE gzfile_s_open(int, VALUE*, VALUE, const char*);
177
+ NORETURN(static void gzfile_raise(struct gzfile *, VALUE, const char *));
178
+ static VALUE gzfile_error_inspect(VALUE);
179
+
180
+ static VALUE rb_gzfile_to_io(VALUE);
181
+ static VALUE rb_gzfile_crc(VALUE);
182
+ static VALUE rb_gzfile_mtime(VALUE);
183
+ static VALUE rb_gzfile_level(VALUE);
184
+ static VALUE rb_gzfile_os_code(VALUE);
185
+ static VALUE rb_gzfile_orig_name(VALUE);
186
+ static VALUE rb_gzfile_comment(VALUE);
187
+ static VALUE rb_gzfile_lineno(VALUE);
188
+ static VALUE rb_gzfile_set_lineno(VALUE, VALUE);
189
+ static VALUE rb_gzfile_set_mtime(VALUE, VALUE);
190
+ static VALUE rb_gzfile_set_orig_name(VALUE, VALUE);
191
+ static VALUE rb_gzfile_set_comment(VALUE, VALUE);
192
+ static VALUE rb_gzfile_close(VALUE);
193
+ static VALUE rb_gzfile_finish(VALUE);
194
+ static VALUE rb_gzfile_closed_p(VALUE);
195
+ static VALUE rb_gzfile_eof_p(VALUE);
196
+ static VALUE rb_gzfile_sync(VALUE);
197
+ static VALUE rb_gzfile_set_sync(VALUE, VALUE);
198
+ static VALUE rb_gzfile_total_in(VALUE);
199
+ static VALUE rb_gzfile_total_out(VALUE);
200
+ static VALUE rb_gzfile_path(VALUE);
201
+
202
+ static VALUE rb_gzwriter_s_allocate(VALUE);
203
+ static VALUE rb_gzwriter_s_open(int, VALUE*, VALUE);
204
+ static VALUE rb_gzwriter_initialize(int, VALUE*, VALUE);
205
+ static VALUE rb_gzwriter_flush(int, VALUE*, VALUE);
206
+ static VALUE rb_gzwriter_write(int, VALUE*, VALUE);
207
+ static VALUE rb_gzwriter_putc(VALUE, VALUE);
208
+
209
+ static VALUE rb_gzreader_s_allocate(VALUE);
210
+ static VALUE rb_gzreader_s_open(int, VALUE*, VALUE);
211
+ static VALUE rb_gzreader_initialize(int, VALUE*, VALUE);
212
+ static VALUE rb_gzreader_rewind(VALUE);
213
+ static VALUE rb_gzreader_unused(VALUE);
214
+ static VALUE rb_gzreader_read(int, VALUE*, VALUE);
215
+ static VALUE rb_gzreader_getc(VALUE);
216
+ static VALUE rb_gzreader_readchar(VALUE);
217
+ static VALUE rb_gzreader_each_byte(VALUE);
218
+ static VALUE rb_gzreader_ungetc(VALUE, VALUE);
219
+ static VALUE rb_gzreader_ungetbyte(VALUE, VALUE);
220
+ static void gzreader_skip_linebreaks(struct gzfile*);
221
+ static VALUE gzreader_gets(int, VALUE*, VALUE);
222
+ static VALUE rb_gzreader_gets(int, VALUE*, VALUE);
223
+ static VALUE rb_gzreader_readline(int, VALUE*, VALUE);
224
+ static VALUE rb_gzreader_each(int, VALUE*, VALUE);
225
+ static VALUE rb_gzreader_readlines(int, VALUE*, VALUE);
226
+ #endif /* GZIP_SUPPORT */
227
+
228
+ /*
229
+ * Document-module: Zlib
230
+ *
231
+ * This module provides access to the {zlib library}[http://zlib.net]. Zlib is
232
+ * designed to be a portable, free, general-purpose, legally unencumbered --
233
+ * that is, not covered by any patents -- lossless data-compression library
234
+ * for use on virtually any computer hardware and operating system.
235
+ *
236
+ * The zlib compression library provides in-memory compression and
237
+ * decompression functions, including integrity checks of the uncompressed
238
+ * data.
239
+ *
240
+ * The zlib compressed data format is described in RFC 1950, which is a
241
+ * wrapper around a deflate stream which is described in RFC 1951.
242
+ *
243
+ * The library also supports reading and writing files in gzip (.gz) format
244
+ * with an interface similar to that of IO. The gzip format is described in
245
+ * RFC 1952 which is also a wrapper around a deflate stream.
246
+ *
247
+ * The zlib format was designed to be compact and fast for use in memory and on
248
+ * communications channels. The gzip format was designed for single-file
249
+ * compression on file systems, has a larger header than zlib to maintain
250
+ * directory information, and uses a different, slower check method than zlib.
251
+ *
252
+ * See your system's zlib.h for further information about zlib
253
+ *
254
+ * == Sample usage
255
+ *
256
+ * Using the wrapper to compress strings with default parameters is quite
257
+ * simple:
258
+ *
259
+ * require "zstdlib"
260
+ *
261
+ * data_to_compress = File.read("don_quixote.txt")
262
+ *
263
+ * puts "Input size: #{data_to_compress.size}"
264
+ * #=> Input size: 2347740
265
+ *
266
+ * data_compressed = Zstdlib::Deflate.deflate(data_to_compress)
267
+ *
268
+ * puts "Compressed size: #{data_compressed.size}"
269
+ * #=> Compressed size: 887238
270
+ *
271
+ * uncompressed_data = Zstdlib::Inflate.inflate(data_compressed)
272
+ *
273
+ * puts "Uncompressed data is: #{uncompressed_data}"
274
+ * #=> Uncompressed data is: The Project Gutenberg EBook of Don Quixote...
275
+ *
276
+ * == Class tree
277
+ *
278
+ * - Zstdlib::Deflate
279
+ * - Zstdlib::Inflate
280
+ * - Zstdlib::ZStream
281
+ * - Zstdlib::Error
282
+ * - Zstdlib::StreamEnd
283
+ * - Zstdlib::NeedDict
284
+ * - Zstdlib::DataError
285
+ * - Zstdlib::StreamError
286
+ * - Zstdlib::MemError
287
+ * - Zstdlib::BufError
288
+ * - Zstdlib::VersionError
289
+ *
290
+ * (if you have GZIP_SUPPORT)
291
+ * - Zstdlib::GzipReader
292
+ * - Zstdlib::GzipWriter
293
+ * - Zstdlib::GzipFile
294
+ * - Zstdlib::GzipFile::Error
295
+ * - Zstdlib::GzipFile::LengthError
296
+ * - Zstdlib::GzipFile::CRCError
297
+ * - Zstdlib::GzipFile::NoFooter
298
+ *
299
+ */
300
+ void Init_zstdlib(void);
301
+
302
+ /*--------- Exceptions --------*/
303
+
304
+ static VALUE cZError, cStreamEnd, cNeedDict;
305
+ static VALUE cStreamError, cDataError, cMemError, cBufError, cVersionError;
306
+
307
+ static void
308
+ raise_zlib_error(int err, const char *msg)
309
+ {
310
+ VALUE exc;
311
+
312
+ if (!msg) {
313
+ msg = zError(err);
314
+ }
315
+
316
+ switch(err) {
317
+ case Z_STREAM_END:
318
+ exc = rb_exc_new2(cStreamEnd, msg);
319
+ break;
320
+ case Z_NEED_DICT:
321
+ exc = rb_exc_new2(cNeedDict, msg);
322
+ break;
323
+ case Z_STREAM_ERROR:
324
+ exc = rb_exc_new2(cStreamError, msg);
325
+ break;
326
+ case Z_DATA_ERROR:
327
+ exc = rb_exc_new2(cDataError, msg);
328
+ break;
329
+ case Z_BUF_ERROR:
330
+ exc = rb_exc_new2(cBufError, msg);
331
+ break;
332
+ case Z_VERSION_ERROR:
333
+ exc = rb_exc_new2(cVersionError, msg);
334
+ break;
335
+ case Z_MEM_ERROR:
336
+ exc = rb_exc_new2(cMemError, msg);
337
+ break;
338
+ case Z_ERRNO:
339
+ rb_sys_fail(msg);
340
+ /* no return */
341
+ default:
342
+ exc = rb_exc_new_str(cZError,
343
+ rb_sprintf("unknown zlib error %d: %s", err, msg));
344
+ }
345
+
346
+ rb_exc_raise(exc);
347
+ }
348
+
349
+
350
+ /*--- Warning (in finalizer) ---*/
351
+
352
+ static void
353
+ finalizer_warn(const char *msg)
354
+ {
355
+ fprintf(stderr, "zlib(finalizer): %s\n", msg);
356
+ }
357
+
358
+
359
+ /*-------- module Zlib --------*/
360
+ /*
361
+ * Document-method: Zstdlib.zstd_version
362
+ *
363
+ * Returns the string which represents the version of zstd library.
364
+ */
365
+ static VALUE
366
+ rb_zstd_version(VALUE klass)
367
+ {
368
+ VALUE str;
369
+ str = rb_str_new2(ZSTD_versionString());
370
+ OBJ_TAINT(str);
371
+ return str;
372
+ }
373
+
374
+ /*
375
+ * Document-method: Zstdlib.zlib_version
376
+ *
377
+ * Returns the string which represents the version of zlib library.
378
+ */
379
+ static VALUE
380
+ rb_zlib_version(VALUE klass)
381
+ {
382
+ return rb_str_new2(zlibVersion());
383
+ }
384
+
385
+ #if SIZEOF_LONG > SIZEOF_INT
386
+ static uLong
387
+ checksum_long(uLong (*func)(uLong, const Bytef*, uInt), uLong sum, const Bytef *ptr, long len)
388
+ {
389
+ if (len > UINT_MAX) {
390
+ do {
391
+ sum = func(sum, ptr, UINT_MAX);
392
+ ptr += UINT_MAX;
393
+ len -= UINT_MAX;
394
+ } while (len >= UINT_MAX);
395
+ }
396
+ if (len > 0) sum = func(sum, ptr, (uInt)len);
397
+ return sum;
398
+ }
399
+ #else
400
+ #define checksum_long(func, sum, ptr, len) (func)((sum), (ptr), (len))
401
+ #endif
402
+
403
+ static VALUE
404
+ do_checksum(int argc, VALUE *argv, uLong (*func)(uLong, const Bytef*, uInt))
405
+ {
406
+ VALUE str, vsum;
407
+ unsigned long sum;
408
+
409
+ rb_scan_args(argc, argv, "02", &str, &vsum);
410
+
411
+ if (!NIL_P(vsum)) {
412
+ sum = NUM2ULONG(vsum);
413
+ }
414
+ else if (NIL_P(str)) {
415
+ sum = 0;
416
+ }
417
+ else {
418
+ sum = func(0, Z_NULL, 0);
419
+ }
420
+
421
+ if (NIL_P(str)) {
422
+ sum = func(sum, Z_NULL, 0);
423
+ }
424
+ else {
425
+ StringValue(str);
426
+ sum = checksum_long(func, sum, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
427
+ }
428
+ return rb_uint2inum(sum);
429
+ }
430
+
431
+ /*
432
+ * Document-method: Zstdlib.adler32
433
+ *
434
+ * call-seq: Zstdlib.adler32(string, adler)
435
+ *
436
+ * Calculates Adler-32 checksum for +string+, and returns updated value of
437
+ * +adler+. If +string+ is omitted, it returns the Adler-32 initial value. If
438
+ * +adler+ is omitted, it assumes that the initial value is given to +adler+.
439
+ *
440
+ * Example usage:
441
+ *
442
+ * require "zstdlib"
443
+ *
444
+ * data = "foo"
445
+ * puts "Adler32 checksum: #{Zstdlib.adler32(data).to_s(16)}"
446
+ * #=> Adler32 checksum: 2820145
447
+ *
448
+ */
449
+ static VALUE
450
+ rb_zlib_adler32(int argc, VALUE *argv, VALUE klass)
451
+ {
452
+ return do_checksum(argc, argv, adler32);
453
+ }
454
+
455
+ #ifdef HAVE_ADLER32_COMBINE
456
+ /*
457
+ * Document-method: Zstdlib.adler32_combine
458
+ *
459
+ * call-seq: Zstdlib.adler32_combine(adler1, adler2, len2)
460
+ *
461
+ * Combine two Adler-32 check values in to one. +alder1+ is the first Adler-32
462
+ * value, +adler2+ is the second Adler-32 value. +len2+ is the length of the
463
+ * string used to generate +adler2+.
464
+ *
465
+ */
466
+ static VALUE
467
+ rb_zlib_adler32_combine(VALUE klass, VALUE adler1, VALUE adler2, VALUE len2)
468
+ {
469
+ return ULONG2NUM(
470
+ adler32_combine(NUM2ULONG(adler1), NUM2ULONG(adler2), NUM2LONG(len2)));
471
+ }
472
+ #else
473
+ #define rb_zlib_adler32_combine rb_f_notimplement
474
+ #endif
475
+
476
+ /*
477
+ * Document-method: Zstdlib.crc32
478
+ *
479
+ * call-seq: Zstdlib.crc32(string, crc)
480
+ *
481
+ * Calculates CRC checksum for +string+, and returns updated value of +crc+. If
482
+ * +string+ is omitted, it returns the CRC initial value. If +crc+ is omitted, it
483
+ * assumes that the initial value is given to +crc+.
484
+ *
485
+ * FIXME: expression.
486
+ */
487
+ static VALUE
488
+ rb_zlib_crc32(int argc, VALUE *argv, VALUE klass)
489
+ {
490
+ return do_checksum(argc, argv, crc32);
491
+ }
492
+
493
+ #ifdef HAVE_CRC32_COMBINE
494
+ /*
495
+ * Document-method: Zstdlib.crc32_combine
496
+ *
497
+ * call-seq: Zstdlib.crc32_combine(crc1, crc2, len2)
498
+ *
499
+ * Combine two CRC-32 check values in to one. +crc1+ is the first CRC-32
500
+ * value, +crc2+ is the second CRC-32 value. +len2+ is the length of the
501
+ * string used to generate +crc2+.
502
+ *
503
+ */
504
+ static VALUE
505
+ rb_zlib_crc32_combine(VALUE klass, VALUE crc1, VALUE crc2, VALUE len2)
506
+ {
507
+ return ULONG2NUM(
508
+ crc32_combine(NUM2ULONG(crc1), NUM2ULONG(crc2), NUM2LONG(len2)));
509
+ }
510
+ #else
511
+ #define rb_zlib_crc32_combine rb_f_notimplement
512
+ #endif
513
+
514
+ /*
515
+ * Document-method: Zstdlib.crc_table
516
+ *
517
+ * Returns the table for calculating CRC checksum as an array.
518
+ */
519
+ static VALUE
520
+ rb_zlib_crc_table(VALUE obj)
521
+ {
522
+ #if !defined(HAVE_TYPE_Z_CRC_T)
523
+ /* z_crc_t is defined since zlib-1.2.7. */
524
+ typedef unsigned long z_crc_t;
525
+ #endif
526
+ const z_crc_t *crctbl;
527
+ VALUE dst;
528
+ int i;
529
+
530
+ crctbl = get_crc_table();
531
+ dst = rb_ary_new2(256);
532
+
533
+ for (i = 0; i < 256; i++) {
534
+ rb_ary_push(dst, rb_uint2inum(crctbl[i]));
535
+ }
536
+ return dst;
537
+ }
538
+
539
+
540
+
541
+ /*-------- zstream - internal APIs --------*/
542
+
543
+ struct zstream {
544
+ unsigned long flags;
545
+ VALUE buf;
546
+ VALUE input;
547
+ z_stream stream;
548
+ const struct zstream_funcs {
549
+ int (*reset)(z_streamp);
550
+ int (*end)(z_streamp);
551
+ int (*run)(z_streamp, int);
552
+ } *func;
553
+ };
554
+
555
+ #define ZSTREAM_FLAG_READY 0x1
556
+ #define ZSTREAM_FLAG_IN_STREAM 0x2
557
+ #define ZSTREAM_FLAG_FINISHED 0x4
558
+ #define ZSTREAM_FLAG_CLOSING 0x8
559
+ #define ZSTREAM_FLAG_GZFILE 0x10 /* disallows yield from expand_buffer for
560
+ gzip*/
561
+ #define ZSTREAM_FLAG_UNUSED 0x20
562
+
563
+ #define ZSTREAM_READY(z) ((z)->flags |= ZSTREAM_FLAG_READY)
564
+ #define ZSTREAM_IS_READY(z) ((z)->flags & ZSTREAM_FLAG_READY)
565
+ #define ZSTREAM_IS_FINISHED(z) ((z)->flags & ZSTREAM_FLAG_FINISHED)
566
+ #define ZSTREAM_IS_CLOSING(z) ((z)->flags & ZSTREAM_FLAG_CLOSING)
567
+ #define ZSTREAM_IS_GZFILE(z) ((z)->flags & ZSTREAM_FLAG_GZFILE)
568
+ #define ZSTREAM_BUF_FILLED(z) (NIL_P((z)->buf) ? 0 : RSTRING_LEN((z)->buf))
569
+
570
+ #define ZSTREAM_EXPAND_BUFFER_OK 0
571
+
572
+ /* I think that more better value should be found,
573
+ but I gave up finding it. B) */
574
+ #define ZSTREAM_INITIAL_BUFSIZE 1024
575
+ /* Allow a quick return when the thread is interrupted */
576
+ #define ZSTREAM_AVAIL_OUT_STEP_MAX 16384
577
+ #define ZSTREAM_AVAIL_OUT_STEP_MIN 2048
578
+
579
+ static const struct zstream_funcs deflate_funcs = {
580
+ deflateReset, deflateEnd, deflate,
581
+ };
582
+
583
+ static const struct zstream_funcs inflate_funcs = {
584
+ inflateReset, inflateEnd, inflate,
585
+ };
586
+
587
+ struct zstream_run_args {
588
+ struct zstream * z;
589
+ int flush; /* stream flush value for inflate() or deflate() */
590
+ int interrupt; /* stop processing the stream and return to ruby */
591
+ int jump_state; /* for buffer expansion block break or exception */
592
+ int stream_output; /* for streaming zlib processing */
593
+ };
594
+
595
+ static voidpf
596
+ zlib_mem_alloc(voidpf opaque, uInt items, uInt size)
597
+ {
598
+ voidpf p = xmalloc2(items, size);
599
+ /* zlib FAQ: Valgrind (or some similar memory access checker) says that
600
+ deflate is performing a conditional jump that depends on an
601
+ uninitialized value. Isn't that a bug?
602
+ http://www.zlib.net/zlib_faq.html#faq36 */
603
+ (void)VALGRIND_MAKE_MEM_DEFINED(p, items * size);
604
+ return p;
605
+ }
606
+
607
+ static void
608
+ zlib_mem_free(voidpf opaque, voidpf address)
609
+ {
610
+ xfree(address);
611
+ }
612
+
613
+ static void
614
+ zstream_init(struct zstream *z, const struct zstream_funcs *func)
615
+ {
616
+ z->flags = 0;
617
+ z->buf = Qnil;
618
+ z->input = Qnil;
619
+ z->stream.zalloc = zlib_mem_alloc;
620
+ z->stream.zfree = zlib_mem_free;
621
+ z->stream.opaque = Z_NULL;
622
+ z->stream.msg = Z_NULL;
623
+ z->stream.next_in = Z_NULL;
624
+ z->stream.avail_in = 0;
625
+ z->stream.next_out = Z_NULL;
626
+ z->stream.avail_out = 0;
627
+ z->func = func;
628
+ }
629
+
630
+ #define zstream_init_deflate(z) zstream_init((z), &deflate_funcs)
631
+ #define zstream_init_inflate(z) zstream_init((z), &inflate_funcs)
632
+
633
+ static void
634
+ zstream_expand_buffer(struct zstream *z)
635
+ {
636
+ if (NIL_P(z->buf)) {
637
+ zstream_expand_buffer_into(z, ZSTREAM_INITIAL_BUFSIZE);
638
+ return;
639
+ }
640
+
641
+ if (!ZSTREAM_IS_GZFILE(z) && rb_block_given_p()) {
642
+ long buf_filled = ZSTREAM_BUF_FILLED(z);
643
+ if (buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
644
+ int state = 0;
645
+
646
+ rb_obj_reveal(z->buf, rb_cString);
647
+
648
+ rb_protect(rb_yield, z->buf, &state);
649
+
650
+ z->buf = Qnil;
651
+ zstream_expand_buffer_into(z, ZSTREAM_AVAIL_OUT_STEP_MAX);
652
+
653
+ if (state)
654
+ rb_jump_tag(state);
655
+
656
+ return;
657
+ }
658
+ else {
659
+ zstream_expand_buffer_into(z,
660
+ ZSTREAM_AVAIL_OUT_STEP_MAX - buf_filled);
661
+ }
662
+ }
663
+ else {
664
+ zstream_expand_buffer_non_stream(z);
665
+ }
666
+ }
667
+
668
+ static void
669
+ zstream_expand_buffer_into(struct zstream *z, unsigned long size)
670
+ {
671
+ if (NIL_P(z->buf)) {
672
+ /* I uses rb_str_new here not rb_str_buf_new because
673
+ rb_str_buf_new makes a zero-length string. */
674
+ z->buf = rb_str_buf_new(size);
675
+ z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf);
676
+ z->stream.avail_out = MAX_UINT(size);
677
+ rb_obj_hide(z->buf);
678
+ }
679
+ else if (z->stream.avail_out != size) {
680
+ rb_str_modify_expand(z->buf, size);
681
+ z->stream.next_out = (Bytef*)RSTRING_END(z->buf);
682
+ z->stream.avail_out = MAX_UINT(size);
683
+ }
684
+ }
685
+
686
+ static void *
687
+ zstream_expand_buffer_protect(void *ptr)
688
+ {
689
+ struct zstream *z = (struct zstream *)ptr;
690
+ int state = 0;
691
+
692
+ rb_protect((VALUE (*)(VALUE))zstream_expand_buffer, (VALUE)z, &state);
693
+
694
+ return (void *)(VALUE)state;
695
+ }
696
+
697
+ static int
698
+ zstream_expand_buffer_non_stream(struct zstream *z)
699
+ {
700
+ long inc, len = ZSTREAM_BUF_FILLED(z);
701
+
702
+ if (rb_str_capacity(z->buf) - len >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
703
+ z->stream.avail_out = ZSTREAM_AVAIL_OUT_STEP_MAX;
704
+ }
705
+ else {
706
+ inc = len / 2;
707
+ if (inc < ZSTREAM_AVAIL_OUT_STEP_MIN) {
708
+ inc = ZSTREAM_AVAIL_OUT_STEP_MIN;
709
+ }
710
+
711
+ rb_str_modify_expand(z->buf, inc);
712
+ z->stream.avail_out = (inc < ZSTREAM_AVAIL_OUT_STEP_MAX) ?
713
+ (int)inc : ZSTREAM_AVAIL_OUT_STEP_MAX;
714
+ }
715
+ z->stream.next_out = (Bytef*)RSTRING_END(z->buf);
716
+
717
+ return ZSTREAM_EXPAND_BUFFER_OK;
718
+ }
719
+
720
+ static void
721
+ zstream_append_buffer(struct zstream *z, const Bytef *src, long len)
722
+ {
723
+ if (NIL_P(z->buf)) {
724
+ z->buf = rb_str_buf_new(len);
725
+ rb_str_buf_cat(z->buf, (const char*)src, len);
726
+ z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf);
727
+ z->stream.avail_out = 0;
728
+ rb_obj_hide(z->buf);
729
+ return;
730
+ }
731
+
732
+ if ((long)rb_str_capacity(z->buf) < ZSTREAM_BUF_FILLED(z) + len) {
733
+ rb_str_modify_expand(z->buf, len);
734
+ z->stream.avail_out = 0;
735
+ }
736
+ else {
737
+ if (z->stream.avail_out >= (uInt)len) {
738
+ z->stream.avail_out -= (uInt)len;
739
+ }
740
+ else {
741
+ z->stream.avail_out = 0;
742
+ }
743
+ }
744
+ rb_str_cat(z->buf, (const char *)src, len);
745
+ z->stream.next_out = (Bytef*)RSTRING_END(z->buf);
746
+ }
747
+
748
+ #define zstream_append_buffer2(z,v) \
749
+ zstream_append_buffer((z),(Bytef*)RSTRING_PTR(v),RSTRING_LEN(v))
750
+
751
+ static VALUE
752
+ zstream_detach_buffer(struct zstream *z)
753
+ {
754
+ VALUE dst;
755
+
756
+ if (!ZSTREAM_IS_FINISHED(z) && !ZSTREAM_IS_GZFILE(z) &&
757
+ rb_block_given_p()) {
758
+ /* prevent tiny yields mid-stream, save for next
759
+ * zstream_expand_buffer() or stream end */
760
+ return Qnil;
761
+ }
762
+
763
+ if (NIL_P(z->buf)) {
764
+ dst = rb_str_new(0, 0);
765
+ }
766
+ else {
767
+ dst = z->buf;
768
+ rb_obj_reveal(dst, rb_cString);
769
+ }
770
+
771
+ z->buf = Qnil;
772
+ z->stream.next_out = 0;
773
+ z->stream.avail_out = 0;
774
+
775
+ if (!ZSTREAM_IS_GZFILE(z) && rb_block_given_p()) {
776
+ rb_yield(dst);
777
+ dst = Qnil;
778
+ }
779
+
780
+ return dst;
781
+ }
782
+
783
+ static VALUE
784
+ zstream_shift_buffer(struct zstream *z, long len)
785
+ {
786
+ VALUE dst;
787
+ char *bufptr;
788
+ long buflen = ZSTREAM_BUF_FILLED(z);
789
+
790
+ if (buflen <= len) {
791
+ return zstream_detach_buffer(z);
792
+ }
793
+
794
+ bufptr = RSTRING_PTR(z->buf);
795
+ dst = rb_str_new(bufptr, len);
796
+ buflen -= len;
797
+ memmove(bufptr, bufptr + len, buflen);
798
+ rb_str_set_len(z->buf, buflen);
799
+ z->stream.next_out = (Bytef*)RSTRING_END(z->buf);
800
+ buflen = (long)rb_str_capacity(z->buf) - ZSTREAM_BUF_FILLED(z);
801
+ if (buflen > ZSTREAM_AVAIL_OUT_STEP_MAX) {
802
+ buflen = ZSTREAM_AVAIL_OUT_STEP_MAX;
803
+ }
804
+ z->stream.avail_out = (uInt)buflen;
805
+
806
+ return dst;
807
+ }
808
+
809
+ static void
810
+ zstream_buffer_ungets(struct zstream *z, const Bytef *b, unsigned long len)
811
+ {
812
+ char *bufptr;
813
+ long filled;
814
+
815
+ if (NIL_P(z->buf) || (long)rb_str_capacity(z->buf) <= ZSTREAM_BUF_FILLED(z)) {
816
+ zstream_expand_buffer_into(z, len);
817
+ }
818
+
819
+ RSTRING_GETMEM(z->buf, bufptr, filled);
820
+ memmove(bufptr + len, bufptr, filled);
821
+ memmove(bufptr, b, len);
822
+ rb_str_set_len(z->buf, filled + len);
823
+ if (z->stream.avail_out > 0) {
824
+ if (len > z->stream.avail_out) len = z->stream.avail_out;
825
+ z->stream.next_out+=len;
826
+ z->stream.avail_out-=(uInt)len;
827
+ }
828
+ }
829
+
830
+ static void
831
+ zstream_buffer_ungetbyte(struct zstream *z, int c)
832
+ {
833
+ Bytef cc = (Bytef)c;
834
+ zstream_buffer_ungets(z, &cc, 1);
835
+ }
836
+
837
+ static void
838
+ zstream_append_input(struct zstream *z, const Bytef *src, long len)
839
+ {
840
+ if (len <= 0) return;
841
+
842
+ if (NIL_P(z->input)) {
843
+ z->input = rb_str_buf_new(len);
844
+ rb_str_buf_cat(z->input, (const char*)src, len);
845
+ rb_obj_hide(z->input);
846
+ }
847
+ else {
848
+ rb_str_buf_cat(z->input, (const char*)src, len);
849
+ }
850
+ }
851
+
852
+ #define zstream_append_input2(z,v)\
853
+ RB_GC_GUARD(v),\
854
+ zstream_append_input((z), (Bytef*)RSTRING_PTR(v), RSTRING_LEN(v))
855
+
856
+ static void
857
+ zstream_discard_input(struct zstream *z, long len)
858
+ {
859
+ if (NIL_P(z->input)) {
860
+ }
861
+ else if (RBASIC_CLASS(z->input) == 0) {
862
+ /* hidden, we created z->input and have complete control */
863
+ char *ptr;
864
+ long oldlen, newlen;
865
+
866
+ RSTRING_GETMEM(z->input, ptr, oldlen);
867
+ newlen = oldlen - len;
868
+ if (newlen > 0) {
869
+ memmove(ptr, ptr + len, newlen);
870
+ }
871
+ if (newlen < 0) {
872
+ newlen = 0;
873
+ }
874
+ rb_str_resize(z->input, newlen);
875
+ if (newlen == 0) {
876
+ rb_gc_force_recycle(z->input);
877
+ z->input = Qnil;
878
+ }
879
+ else {
880
+ rb_str_set_len(z->input, newlen);
881
+ }
882
+ }
883
+ else { /* do not mangle user-provided data */
884
+ if (RSTRING_LEN(z->input) <= len) {
885
+ z->input = Qnil;
886
+ }
887
+ else {
888
+ z->input = rb_str_substr(z->input, len,
889
+ RSTRING_LEN(z->input) - len);
890
+ }
891
+ }
892
+ }
893
+
894
+ static void
895
+ zstream_reset_input(struct zstream *z)
896
+ {
897
+ if (!NIL_P(z->input) && RBASIC_CLASS(z->input) == 0) {
898
+ rb_str_resize(z->input, 0);
899
+ }
900
+ else {
901
+ z->input = Qnil;
902
+ }
903
+ }
904
+
905
+ static void
906
+ zstream_passthrough_input(struct zstream *z)
907
+ {
908
+ if (!NIL_P(z->input)) {
909
+ zstream_append_buffer2(z, z->input);
910
+ z->input = Qnil;
911
+ }
912
+ }
913
+
914
+ static VALUE
915
+ zstream_detach_input(struct zstream *z)
916
+ {
917
+ VALUE dst;
918
+
919
+ if (NIL_P(z->input)) {
920
+ dst = rb_str_new(0, 0);
921
+ }
922
+ else {
923
+ dst = z->input;
924
+ rb_obj_reveal(dst, rb_cString);
925
+ }
926
+ z->input = Qnil;
927
+ return dst;
928
+ }
929
+
930
+ static void
931
+ zstream_reset(struct zstream *z)
932
+ {
933
+ int err;
934
+
935
+ err = z->func->reset(&z->stream);
936
+ if (err != Z_OK) {
937
+ raise_zlib_error(err, z->stream.msg);
938
+ }
939
+ z->flags = ZSTREAM_FLAG_READY;
940
+ z->buf = Qnil;
941
+ z->stream.next_out = 0;
942
+ z->stream.avail_out = 0;
943
+ zstream_reset_input(z);
944
+ }
945
+
946
+ static VALUE
947
+ zstream_end(struct zstream *z)
948
+ {
949
+ int err;
950
+
951
+ if (!ZSTREAM_IS_READY(z)) {
952
+ rb_warning("attempt to close uninitialized zstream; ignored.");
953
+ return Qnil;
954
+ }
955
+ if (z->flags & ZSTREAM_FLAG_IN_STREAM) {
956
+ rb_warning("attempt to close unfinished zstream; reset forced.");
957
+ zstream_reset(z);
958
+ }
959
+
960
+ zstream_reset_input(z);
961
+ err = z->func->end(&z->stream);
962
+ if (err != Z_OK) {
963
+ raise_zlib_error(err, z->stream.msg);
964
+ }
965
+ z->flags = 0;
966
+ return Qnil;
967
+ }
968
+
969
+ static VALUE
970
+ zstream_ensure_end(VALUE v)
971
+ {
972
+ return zstream_end((struct zstream *)v);
973
+ }
974
+
975
+ static void *
976
+ zstream_run_func(void *ptr)
977
+ {
978
+ struct zstream_run_args *args = (struct zstream_run_args *)ptr;
979
+ int err, state, flush = args->flush;
980
+ struct zstream *z = args->z;
981
+ uInt n;
982
+
983
+ err = Z_OK;
984
+ while (!args->interrupt) {
985
+ n = z->stream.avail_out;
986
+ err = z->func->run(&z->stream, flush);
987
+ rb_str_set_len(z->buf, ZSTREAM_BUF_FILLED(z) + (n - z->stream.avail_out));
988
+
989
+ if (err == Z_STREAM_END) {
990
+ z->flags &= ~ZSTREAM_FLAG_IN_STREAM;
991
+ z->flags |= ZSTREAM_FLAG_FINISHED;
992
+ break;
993
+ }
994
+
995
+ if (err != Z_OK && err != Z_BUF_ERROR)
996
+ break;
997
+
998
+ if (z->stream.avail_out > 0) {
999
+ z->flags |= ZSTREAM_FLAG_IN_STREAM;
1000
+ break;
1001
+ }
1002
+
1003
+ if (z->stream.avail_in == 0 && z->func == &inflate_funcs) {
1004
+ /* break here because inflate() return Z_BUF_ERROR when avail_in == 0. */
1005
+ /* but deflate() could be called with avail_in == 0 (there's hidden buffer
1006
+ in zstream->state) */
1007
+ z->flags |= ZSTREAM_FLAG_IN_STREAM;
1008
+ break;
1009
+ }
1010
+
1011
+ if (args->stream_output) {
1012
+ state = (int)(VALUE)rb_thread_call_with_gvl(zstream_expand_buffer_protect,
1013
+ (void *)z);
1014
+ }
1015
+ else {
1016
+ state = zstream_expand_buffer_non_stream(z);
1017
+ }
1018
+
1019
+ if (state) {
1020
+ err = Z_OK; /* buffer expanded but stream processing was stopped */
1021
+ args->jump_state = state;
1022
+ break;
1023
+ }
1024
+ }
1025
+
1026
+ return (void *)(VALUE)err;
1027
+ }
1028
+
1029
+ /*
1030
+ * There is no safe way to interrupt z->run->func().
1031
+ * async-signal-safe
1032
+ */
1033
+ static void
1034
+ zstream_unblock_func(void *ptr)
1035
+ {
1036
+ struct zstream_run_args *args = (struct zstream_run_args *)ptr;
1037
+
1038
+ args->interrupt = 1;
1039
+ }
1040
+
1041
+ static void
1042
+ zstream_run(struct zstream *z, Bytef *src, long len, int flush)
1043
+ {
1044
+ struct zstream_run_args args;
1045
+ int err;
1046
+ VALUE old_input = Qnil;
1047
+
1048
+ args.z = z;
1049
+ args.flush = flush;
1050
+ args.interrupt = 0;
1051
+ args.jump_state = 0;
1052
+ args.stream_output = !ZSTREAM_IS_GZFILE(z) && rb_block_given_p();
1053
+
1054
+ if (NIL_P(z->input) && len == 0) {
1055
+ z->stream.next_in = (Bytef*)"";
1056
+ z->stream.avail_in = 0;
1057
+ }
1058
+ else {
1059
+ zstream_append_input(z, src, len);
1060
+ /* keep reference to `z->input' so as not to be garbage collected
1061
+ after zstream_reset_input() and prevent `z->stream.next_in'
1062
+ from dangling. */
1063
+ old_input = zstream_detach_input(z);
1064
+ rb_obj_hide(old_input); /* for GVL release and later recycle */
1065
+ z->stream.next_in = (Bytef*)RSTRING_PTR(old_input);
1066
+ z->stream.avail_in = MAX_UINT(RSTRING_LEN(old_input));
1067
+ }
1068
+
1069
+ if (z->stream.avail_out == 0) {
1070
+ zstream_expand_buffer(z);
1071
+ }
1072
+
1073
+ loop:
1074
+ #ifndef RB_NOGVL_UBF_ASYNC_SAFE
1075
+ err = (int)(VALUE)rb_thread_call_without_gvl(zstream_run_func, (void *)&args,
1076
+ zstream_unblock_func, (void *)&args);
1077
+ #else
1078
+ err = (int)(VALUE)rb_nogvl(zstream_run_func, (void *)&args,
1079
+ zstream_unblock_func, (void *)&args,
1080
+ RB_NOGVL_UBF_ASYNC_SAFE);
1081
+ #endif
1082
+
1083
+ if (flush != Z_FINISH && err == Z_BUF_ERROR
1084
+ && z->stream.avail_out > 0) {
1085
+ z->flags |= ZSTREAM_FLAG_IN_STREAM;
1086
+ }
1087
+
1088
+ zstream_reset_input(z);
1089
+
1090
+ if (err != Z_OK && err != Z_STREAM_END) {
1091
+ if (z->stream.avail_in > 0) {
1092
+ zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
1093
+ }
1094
+ if (err == Z_NEED_DICT) {
1095
+ VALUE self = (VALUE)z->stream.opaque;
1096
+ if (self) {
1097
+ VALUE dicts = rb_ivar_get(self, id_dictionaries);
1098
+ VALUE dict = rb_hash_aref(dicts, rb_uint2inum(z->stream.adler));
1099
+ if (!NIL_P(dict)) {
1100
+ rb_inflate_set_dictionary(self, dict);
1101
+ goto loop;
1102
+ }
1103
+ }
1104
+ }
1105
+ raise_zlib_error(err, z->stream.msg);
1106
+ }
1107
+
1108
+ if (z->stream.avail_in > 0) {
1109
+ zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
1110
+ }
1111
+ if (!NIL_P(old_input)) {
1112
+ rb_str_resize(old_input, 0);
1113
+ rb_gc_force_recycle(old_input);
1114
+ }
1115
+
1116
+ if (args.jump_state)
1117
+ rb_jump_tag(args.jump_state);
1118
+ }
1119
+
1120
+ static VALUE
1121
+ zstream_sync(struct zstream *z, Bytef *src, long len)
1122
+ {
1123
+ /* VALUE rest; */
1124
+ int err;
1125
+
1126
+ if (!NIL_P(z->input)) {
1127
+ z->stream.next_in = (Bytef*)RSTRING_PTR(z->input);
1128
+ z->stream.avail_in = MAX_UINT(RSTRING_LEN(z->input));
1129
+ err = inflateSync(&z->stream);
1130
+ if (err == Z_OK) {
1131
+ zstream_discard_input(z,
1132
+ RSTRING_LEN(z->input) - z->stream.avail_in);
1133
+ zstream_append_input(z, src, len);
1134
+ return Qtrue;
1135
+ }
1136
+ zstream_reset_input(z);
1137
+ if (err != Z_DATA_ERROR) {
1138
+ /* rest = rb_str_new((char*)z->stream.next_in, z->stream.avail_in); */
1139
+ raise_zlib_error(err, z->stream.msg);
1140
+ }
1141
+ }
1142
+
1143
+ if (len <= 0) return Qfalse;
1144
+
1145
+ z->stream.next_in = src;
1146
+ z->stream.avail_in = MAX_UINT(len);
1147
+ err = inflateSync(&z->stream);
1148
+ if (err == Z_OK) {
1149
+ zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
1150
+ return Qtrue;
1151
+ }
1152
+ if (err != Z_DATA_ERROR) {
1153
+ /* rest = rb_str_new((char*)z->stream.next_in, z->stream.avail_in); */
1154
+ raise_zlib_error(err, z->stream.msg);
1155
+ }
1156
+ return Qfalse;
1157
+ }
1158
+
1159
+ static void
1160
+ zstream_mark(void *p)
1161
+ {
1162
+ struct zstream *z = p;
1163
+ rb_gc_mark(z->buf);
1164
+ rb_gc_mark(z->input);
1165
+ }
1166
+
1167
+ static void
1168
+ zstream_finalize(struct zstream *z)
1169
+ {
1170
+ int err = z->func->end(&z->stream);
1171
+ if (err == Z_STREAM_ERROR)
1172
+ finalizer_warn("the stream state was inconsistent.");
1173
+ if (err == Z_DATA_ERROR)
1174
+ finalizer_warn("the stream was freed prematurely.");
1175
+ }
1176
+
1177
+ static void
1178
+ zstream_free(void *p)
1179
+ {
1180
+ struct zstream *z = p;
1181
+
1182
+ if (ZSTREAM_IS_READY(z)) {
1183
+ zstream_finalize(z);
1184
+ }
1185
+ xfree(z);
1186
+ }
1187
+
1188
+ static size_t
1189
+ zstream_memsize(const void *p)
1190
+ {
1191
+ /* n.b. this does not track memory managed via zalloc/zfree callbacks */
1192
+ return sizeof(struct zstream);
1193
+ }
1194
+
1195
+ static const rb_data_type_t zstream_data_type = {
1196
+ "zstream",
1197
+ { zstream_mark, zstream_free, zstream_memsize, },
1198
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
1199
+ };
1200
+
1201
+ static VALUE
1202
+ zstream_new(VALUE klass, const struct zstream_funcs *funcs)
1203
+ {
1204
+ VALUE obj;
1205
+ struct zstream *z;
1206
+
1207
+ obj = TypedData_Make_Struct(klass, struct zstream, &zstream_data_type, z);
1208
+ zstream_init(z, funcs);
1209
+ z->stream.opaque = (voidpf)obj;
1210
+ return obj;
1211
+ }
1212
+
1213
+ #define zstream_deflate_new(klass) zstream_new((klass), &deflate_funcs)
1214
+ #define zstream_inflate_new(klass) zstream_new((klass), &inflate_funcs)
1215
+
1216
+ static struct zstream *
1217
+ get_zstream(VALUE obj)
1218
+ {
1219
+ struct zstream *z;
1220
+
1221
+ TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z);
1222
+ if (!ZSTREAM_IS_READY(z)) {
1223
+ rb_raise(cZError, "stream is not ready");
1224
+ }
1225
+ return z;
1226
+ }
1227
+
1228
+
1229
+ /* ------------------------------------------------------------------------- */
1230
+
1231
+ /*
1232
+ * Document-class: Zstdlib::ZStream
1233
+ *
1234
+ * Zstdlib::ZStream is the abstract class for the stream which handles the
1235
+ * compressed data. The operations are defined in the subclasses:
1236
+ * Zstdlib::Deflate for compression, and Zstdlib::Inflate for decompression.
1237
+ *
1238
+ * An instance of Zstdlib::ZStream has one stream (struct zstream in the source)
1239
+ * and two variable-length buffers which associated to the input (next_in) of
1240
+ * the stream and the output (next_out) of the stream. In this document,
1241
+ * "input buffer" means the buffer for input, and "output buffer" means the
1242
+ * buffer for output.
1243
+ *
1244
+ * Data input into an instance of Zstdlib::ZStream are temporally stored into
1245
+ * the end of input buffer, and then data in input buffer are processed from
1246
+ * the beginning of the buffer until no more output from the stream is
1247
+ * produced (i.e. until avail_out > 0 after processing). During processing,
1248
+ * output buffer is allocated and expanded automatically to hold all output
1249
+ * data.
1250
+ *
1251
+ * Some particular instance methods consume the data in output buffer and
1252
+ * return them as a String.
1253
+ *
1254
+ * Here is an ascii art for describing above:
1255
+ *
1256
+ * +================ an instance of Zstdlib::ZStream ================+
1257
+ * || ||
1258
+ * || +--------+ +-------+ +--------+ ||
1259
+ * || +--| output |<---------|zstream|<---------| input |<--+ ||
1260
+ * || | | buffer | next_out+-------+next_in | buffer | | ||
1261
+ * || | +--------+ +--------+ | ||
1262
+ * || | | ||
1263
+ * +===|======================================================|===+
1264
+ * | |
1265
+ * v |
1266
+ * "output data" "input data"
1267
+ *
1268
+ * If an error occurs during processing input buffer, an exception which is a
1269
+ * subclass of Zstdlib::Error is raised. At that time, both input and output
1270
+ * buffer keep their conditions at the time when the error occurs.
1271
+ *
1272
+ * == Method Catalogue
1273
+ *
1274
+ * Many of the methods in this class are fairly low-level and unlikely to be
1275
+ * of interest to users. In fact, users are unlikely to use this class
1276
+ * directly; rather they will be interested in Zstdlib::Inflate and
1277
+ * Zstdlib::Deflate.
1278
+ *
1279
+ * The higher level methods are listed below.
1280
+ *
1281
+ * - #total_in
1282
+ * - #total_out
1283
+ * - #data_type
1284
+ * - #adler
1285
+ * - #reset
1286
+ * - #finish
1287
+ * - #finished?
1288
+ * - #close
1289
+ * - #closed?
1290
+ */
1291
+
1292
+ /*
1293
+ * Closes the stream. All operations on the closed stream will raise an
1294
+ * exception.
1295
+ */
1296
+ static VALUE
1297
+ rb_zstream_end(VALUE obj)
1298
+ {
1299
+ zstream_end(get_zstream(obj));
1300
+ return Qnil;
1301
+ }
1302
+
1303
+ /*
1304
+ * Resets and initializes the stream. All data in both input and output buffer
1305
+ * are discarded.
1306
+ */
1307
+ static VALUE
1308
+ rb_zstream_reset(VALUE obj)
1309
+ {
1310
+ zstream_reset(get_zstream(obj));
1311
+ return Qnil;
1312
+ }
1313
+
1314
+ /*
1315
+ * call-seq:
1316
+ * finish -> String
1317
+ * finish { |chunk| ... } -> nil
1318
+ *
1319
+ * Finishes the stream and flushes output buffer. If a block is given each
1320
+ * chunk is yielded to the block until the input buffer has been flushed to
1321
+ * the output buffer.
1322
+ */
1323
+ static VALUE
1324
+ rb_zstream_finish(VALUE obj)
1325
+ {
1326
+ struct zstream *z = get_zstream(obj);
1327
+
1328
+ zstream_run(z, (Bytef*)"", 0, Z_FINISH);
1329
+
1330
+ return zstream_detach_buffer(z);
1331
+ }
1332
+
1333
+ /*
1334
+ * call-seq:
1335
+ * flush_next_in -> input
1336
+ *
1337
+ */
1338
+ static VALUE
1339
+ rb_zstream_flush_next_in(VALUE obj)
1340
+ {
1341
+ struct zstream *z;
1342
+ VALUE dst;
1343
+
1344
+ TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z);
1345
+ dst = zstream_detach_input(z);
1346
+ return dst;
1347
+ }
1348
+
1349
+ /*
1350
+ * call-seq:
1351
+ * flush_next_out -> String
1352
+ * flush_next_out { |chunk| ... } -> nil
1353
+ *
1354
+ * Flushes output buffer and returns all data in that buffer. If a block is
1355
+ * given each chunk is yielded to the block until the current output buffer
1356
+ * has been flushed.
1357
+ */
1358
+ static VALUE
1359
+ rb_zstream_flush_next_out(VALUE obj)
1360
+ {
1361
+ struct zstream *z;
1362
+
1363
+ TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z);
1364
+
1365
+ return zstream_detach_buffer(z);
1366
+ }
1367
+
1368
+ /*
1369
+ * Returns number of bytes of free spaces in output buffer. Because the free
1370
+ * space is allocated automatically, this method returns 0 normally.
1371
+ */
1372
+ static VALUE
1373
+ rb_zstream_avail_out(VALUE obj)
1374
+ {
1375
+ struct zstream *z;
1376
+ TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z);
1377
+ return rb_uint2inum(z->stream.avail_out);
1378
+ }
1379
+
1380
+ /*
1381
+ * Allocates +size+ bytes of free space in the output buffer. If there are more
1382
+ * than +size+ bytes already in the buffer, the buffer is truncated. Because
1383
+ * free space is allocated automatically, you usually don't need to use this
1384
+ * method.
1385
+ */
1386
+ static VALUE
1387
+ rb_zstream_set_avail_out(VALUE obj, VALUE size)
1388
+ {
1389
+ struct zstream *z = get_zstream(obj);
1390
+
1391
+ zstream_expand_buffer_into(z, FIX2INT(size));
1392
+ return size;
1393
+ }
1394
+
1395
+ /*
1396
+ * Returns bytes of data in the input buffer. Normally, returns 0.
1397
+ */
1398
+ static VALUE
1399
+ rb_zstream_avail_in(VALUE obj)
1400
+ {
1401
+ struct zstream *z;
1402
+ TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z);
1403
+ return INT2FIX(NIL_P(z->input) ? 0 : (int)(RSTRING_LEN(z->input)));
1404
+ }
1405
+
1406
+ /*
1407
+ * Returns the total bytes of the input data to the stream. FIXME
1408
+ */
1409
+ static VALUE
1410
+ rb_zstream_total_in(VALUE obj)
1411
+ {
1412
+ return rb_uint2inum(get_zstream(obj)->stream.total_in);
1413
+ }
1414
+
1415
+ /*
1416
+ * Returns the total bytes of the output data from the stream. FIXME
1417
+ */
1418
+ static VALUE
1419
+ rb_zstream_total_out(VALUE obj)
1420
+ {
1421
+ return rb_uint2inum(get_zstream(obj)->stream.total_out);
1422
+ }
1423
+
1424
+ /*
1425
+ * Guesses the type of the data which have been inputed into the stream. The
1426
+ * returned value is either <tt>BINARY</tt>, <tt>ASCII</tt>, or
1427
+ * <tt>UNKNOWN</tt>.
1428
+ */
1429
+ static VALUE
1430
+ rb_zstream_data_type(VALUE obj)
1431
+ {
1432
+ return INT2FIX(get_zstream(obj)->stream.data_type);
1433
+ }
1434
+
1435
+ /*
1436
+ * Returns the adler-32 checksum.
1437
+ */
1438
+ static VALUE
1439
+ rb_zstream_adler(VALUE obj)
1440
+ {
1441
+ return rb_uint2inum(get_zstream(obj)->stream.adler);
1442
+ }
1443
+
1444
+ /*
1445
+ * Returns true if the stream is finished.
1446
+ */
1447
+ static VALUE
1448
+ rb_zstream_finished_p(VALUE obj)
1449
+ {
1450
+ return ZSTREAM_IS_FINISHED(get_zstream(obj)) ? Qtrue : Qfalse;
1451
+ }
1452
+
1453
+ /*
1454
+ * Returns true if the stream is closed.
1455
+ */
1456
+ static VALUE
1457
+ rb_zstream_closed_p(VALUE obj)
1458
+ {
1459
+ struct zstream *z;
1460
+ TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z);
1461
+ return ZSTREAM_IS_READY(z) ? Qfalse : Qtrue;
1462
+ }
1463
+
1464
+
1465
+ /* ------------------------------------------------------------------------- */
1466
+
1467
+ /*
1468
+ * Document-class: Zstdlib::Deflate
1469
+ *
1470
+ * Zstdlib::Deflate is the class for compressing data. See Zstdlib::ZStream for more
1471
+ * information.
1472
+ */
1473
+
1474
+ #define FIXNUMARG(val, ifnil) \
1475
+ (NIL_P((val)) ? (ifnil) \
1476
+ : (FIX2INT((val))))
1477
+
1478
+ #define ARG_LEVEL(val) FIXNUMARG((val), ZSTD_CLEVEL_DEFAULT)
1479
+ #define ARG_WBITS(val) FIXNUMARG((val), MAX_WBITS)
1480
+ #define ARG_MEMLEVEL(val) FIXNUMARG((val), DEF_MEM_LEVEL)
1481
+ #define ARG_STRATEGY(val) FIXNUMARG((val), Z_DEFAULT_STRATEGY)
1482
+ #define ARG_FLUSH(val) FIXNUMARG((val), Z_NO_FLUSH)
1483
+
1484
+
1485
+ static VALUE
1486
+ rb_deflate_s_allocate(VALUE klass)
1487
+ {
1488
+ return zstream_deflate_new(klass);
1489
+ }
1490
+
1491
+ /*
1492
+ * Document-method: Zstdlib::Deflate.new
1493
+ *
1494
+ * call-seq:
1495
+ * Zstdlib::Deflate.new(level=DEFAULT_COMPRESSION, window_bits=MAX_WBITS, mem_level=DEF_MEM_LEVEL, strategy=DEFAULT_STRATEGY)
1496
+ *
1497
+ * Creates a new deflate stream for compression. If a given argument is nil,
1498
+ * the default value of that argument is used.
1499
+ *
1500
+ * The +level+ sets the compression level for the deflate stream between 0 (no
1501
+ * compression) and 9 (best compression). The following constants have been
1502
+ * defined to make code more readable:
1503
+ *
1504
+ * * Zstdlib::DEFAULT_COMPRESSION
1505
+ * * Zstdlib::NO_COMPRESSION
1506
+ * * Zstdlib::BEST_SPEED
1507
+ * * Zstdlib::BEST_COMPRESSION
1508
+ *
1509
+ * See http://www.zlib.net/manual.html#Constants for further information.
1510
+ *
1511
+ * The +window_bits+ sets the size of the history buffer and should be between
1512
+ * 8 and 15. Larger values of this parameter result in better compression at
1513
+ * the expense of memory usage.
1514
+ *
1515
+ * The +mem_level+ specifies how much memory should be allocated for the
1516
+ * internal compression state. 1 uses minimum memory but is slow and reduces
1517
+ * compression ratio while 9 uses maximum memory for optimal speed. The
1518
+ * default value is 8. Two constants are defined:
1519
+ *
1520
+ * * Zstdlib::DEF_MEM_LEVEL
1521
+ * * Zstdlib::MAX_MEM_LEVEL
1522
+ *
1523
+ * The +strategy+ sets the deflate compression strategy. The following
1524
+ * strategies are available:
1525
+ *
1526
+ * Zstdlib::DEFAULT_STRATEGY:: For normal data
1527
+ * Zstdlib::FILTERED:: For data produced by a filter or predictor
1528
+ * Zstdlib::FIXED:: Prevents dynamic Huffman codes
1529
+ * Zstdlib::HUFFMAN_ONLY:: Prevents string matching
1530
+ * Zstdlib::RLE:: Designed for better compression of PNG image data
1531
+ *
1532
+ * See the constants for further description.
1533
+ *
1534
+ * == Examples
1535
+ *
1536
+ * === Basic
1537
+ *
1538
+ * open "compressed.file", "w+" do |io|
1539
+ * io << Zstdlib::Deflate.new.deflate(File.read("big.file"))
1540
+ * end
1541
+ *
1542
+ * === Custom compression
1543
+ *
1544
+ * open "compressed.file", "w+" do |compressed_io|
1545
+ * deflate = Zstdlib::Deflate.new(Zstdlib::BEST_COMPRESSION,
1546
+ * Zstdlib::MAX_WBITS,
1547
+ * Zstdlib::MAX_MEM_LEVEL,
1548
+ * Zstdlib::HUFFMAN_ONLY)
1549
+ *
1550
+ * begin
1551
+ * open "big.file" do |big_io|
1552
+ * until big_io.eof? do
1553
+ * compressed_io << zd.deflate(big_io.read(16384))
1554
+ * end
1555
+ * end
1556
+ * ensure
1557
+ * deflate.close
1558
+ * end
1559
+ * end
1560
+ *
1561
+ * While this example will work, for best optimization review the flags for
1562
+ * your specific time, memory usage and output space requirements.
1563
+ */
1564
+ static VALUE
1565
+ rb_deflate_initialize(int argc, VALUE *argv, VALUE obj)
1566
+ {
1567
+ struct zstream *z;
1568
+ VALUE level, wbits, memlevel, strategy;
1569
+ int err;
1570
+
1571
+ rb_scan_args(argc, argv, "04", &level, &wbits, &memlevel, &strategy);
1572
+ TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z);
1573
+
1574
+ err = deflateInit2(&z->stream, ARG_LEVEL(level), Z_DEFLATED,
1575
+ ARG_WBITS(wbits), ARG_MEMLEVEL(memlevel),
1576
+ ARG_STRATEGY(strategy));
1577
+ if (err != Z_OK) {
1578
+ raise_zlib_error(err, z->stream.msg);
1579
+ }
1580
+ ZSTREAM_READY(z);
1581
+
1582
+ return obj;
1583
+ }
1584
+
1585
+ /*
1586
+ * Document-method: Zstdlib::Deflate#initialize_copy
1587
+ *
1588
+ * Duplicates the deflate stream.
1589
+ */
1590
+ static VALUE
1591
+ rb_deflate_init_copy(VALUE self, VALUE orig)
1592
+ {
1593
+ struct zstream *z1, *z2;
1594
+ int err;
1595
+
1596
+ TypedData_Get_Struct(self, struct zstream, &zstream_data_type, z1);
1597
+ z2 = get_zstream(orig);
1598
+
1599
+ if (z1 == z2) return self;
1600
+ err = deflateCopy(&z1->stream, &z2->stream);
1601
+ if (err != Z_OK) {
1602
+ raise_zlib_error(err, 0);
1603
+ }
1604
+ z1->input = NIL_P(z2->input) ? Qnil : rb_str_dup(z2->input);
1605
+ z1->buf = NIL_P(z2->buf) ? Qnil : rb_str_dup(z2->buf);
1606
+ z1->flags = z2->flags;
1607
+
1608
+ return self;
1609
+ }
1610
+
1611
+ static VALUE
1612
+ deflate_run(VALUE args)
1613
+ {
1614
+ struct zstream *z = (struct zstream*)((VALUE*)args)[0];
1615
+ VALUE src = ((VALUE*)args)[1];
1616
+
1617
+ zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), Z_FINISH);
1618
+ return zstream_detach_buffer(z);
1619
+ }
1620
+
1621
+ /*
1622
+ * Document-method: Zstdlib::Deflate.deflate
1623
+ *
1624
+ * call-seq:
1625
+ * Zstdlib.deflate(string[, level])
1626
+ * Zstdlib::Deflate.deflate(string[, level])
1627
+ *
1628
+ * Compresses the given +string+. Valid values of level are
1629
+ * Zstdlib::NO_COMPRESSION, Zstdlib::BEST_SPEED, Zstdlib::BEST_COMPRESSION,
1630
+ * Zstdlib::DEFAULT_COMPRESSION, or an integer from 0 to 9.
1631
+ *
1632
+ * This method is almost equivalent to the following code:
1633
+ *
1634
+ * def deflate(string, level)
1635
+ * z = Zstdlib::Deflate.new(level)
1636
+ * dst = z.deflate(string, Zstdlib::FINISH)
1637
+ * z.close
1638
+ * dst
1639
+ * end
1640
+ *
1641
+ * See also Zstdlib.inflate
1642
+ *
1643
+ */
1644
+ static VALUE
1645
+ rb_deflate_s_deflate(int argc, VALUE *argv, VALUE klass)
1646
+ {
1647
+ struct zstream z;
1648
+ VALUE src, level, dst, args[2];
1649
+ int err, lev;
1650
+
1651
+ rb_scan_args(argc, argv, "11", &src, &level);
1652
+
1653
+ lev = ARG_LEVEL(level);
1654
+ StringValue(src);
1655
+ zstream_init_deflate(&z);
1656
+ err = deflateInit(&z.stream, lev);
1657
+ if (err != Z_OK) {
1658
+ raise_zlib_error(err, z.stream.msg);
1659
+ }
1660
+ ZSTREAM_READY(&z);
1661
+
1662
+ args[0] = (VALUE)&z;
1663
+ args[1] = src;
1664
+ dst = rb_ensure(deflate_run, (VALUE)args, zstream_ensure_end, (VALUE)&z);
1665
+
1666
+ return dst;
1667
+ }
1668
+
1669
+ static void
1670
+ do_deflate(struct zstream *z, VALUE src, int flush)
1671
+ {
1672
+ if (NIL_P(src)) {
1673
+ zstream_run(z, (Bytef*)"", 0, Z_FINISH);
1674
+ return;
1675
+ }
1676
+ StringValue(src);
1677
+ if (flush != Z_NO_FLUSH || RSTRING_LEN(src) > 0) { /* prevent BUF_ERROR */
1678
+ zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), flush);
1679
+ }
1680
+ }
1681
+
1682
+ /*
1683
+ * Document-method: Zstdlib::Deflate#deflate
1684
+ *
1685
+ * call-seq:
1686
+ * z.deflate(string, flush = Zstdlib::NO_FLUSH) -> String
1687
+ * z.deflate(string, flush = Zstdlib::NO_FLUSH) { |chunk| ... } -> nil
1688
+ *
1689
+ * Inputs +string+ into the deflate stream and returns the output from the
1690
+ * stream. On calling this method, both the input and the output buffers of
1691
+ * the stream are flushed. If +string+ is nil, this method finishes the
1692
+ * stream, just like Zstdlib::ZStream#finish.
1693
+ *
1694
+ * If a block is given consecutive deflated chunks from the +string+ are
1695
+ * yielded to the block and +nil+ is returned.
1696
+ *
1697
+ * The +flush+ parameter specifies the flush mode. The following constants
1698
+ * may be used:
1699
+ *
1700
+ * Zstdlib::NO_FLUSH:: The default
1701
+ * Zstdlib::SYNC_FLUSH:: Flushes the output to a byte boundary
1702
+ * Zstdlib::FULL_FLUSH:: SYNC_FLUSH + resets the compression state
1703
+ * Zstdlib::FINISH:: Pending input is processed, pending output is flushed.
1704
+ *
1705
+ * See the constants for further description.
1706
+ *
1707
+ */
1708
+ static VALUE
1709
+ rb_deflate_deflate(int argc, VALUE *argv, VALUE obj)
1710
+ {
1711
+ struct zstream *z = get_zstream(obj);
1712
+ VALUE src, flush;
1713
+
1714
+ rb_scan_args(argc, argv, "11", &src, &flush);
1715
+ do_deflate(z, src, ARG_FLUSH(flush));
1716
+
1717
+ return zstream_detach_buffer(z);
1718
+ }
1719
+
1720
+ /*
1721
+ * Document-method: Zstdlib::Deflate#<<
1722
+ *
1723
+ * call-seq: << string
1724
+ *
1725
+ * Inputs +string+ into the deflate stream just like Zstdlib::Deflate#deflate, but
1726
+ * returns the Zstdlib::Deflate object itself. The output from the stream is
1727
+ * preserved in output buffer.
1728
+ */
1729
+ static VALUE
1730
+ rb_deflate_addstr(VALUE obj, VALUE src)
1731
+ {
1732
+ do_deflate(get_zstream(obj), src, Z_NO_FLUSH);
1733
+ return obj;
1734
+ }
1735
+
1736
+ /*
1737
+ * Document-method: Zstdlib::Deflate#flush
1738
+ *
1739
+ * call-seq:
1740
+ * flush(flush = Zstdlib::SYNC_FLUSH) -> String
1741
+ * flush(flush = Zstdlib::SYNC_FLUSH) { |chunk| ... } -> nil
1742
+ *
1743
+ * This method is equivalent to <tt>deflate('', flush)</tt>. This method is
1744
+ * just provided to improve the readability of your Ruby program. If a block
1745
+ * is given chunks of deflate output are yielded to the block until the buffer
1746
+ * is flushed.
1747
+ *
1748
+ * See Zstdlib::Deflate#deflate for detail on the +flush+ constants NO_FLUSH,
1749
+ * SYNC_FLUSH, FULL_FLUSH and FINISH.
1750
+ */
1751
+ static VALUE
1752
+ rb_deflate_flush(int argc, VALUE *argv, VALUE obj)
1753
+ {
1754
+ struct zstream *z = get_zstream(obj);
1755
+ VALUE v_flush;
1756
+ int flush;
1757
+
1758
+ rb_scan_args(argc, argv, "01", &v_flush);
1759
+ flush = FIXNUMARG(v_flush, Z_SYNC_FLUSH);
1760
+ if (flush != Z_NO_FLUSH) { /* prevent Z_BUF_ERROR */
1761
+ zstream_run(z, (Bytef*)"", 0, flush);
1762
+ }
1763
+
1764
+ return zstream_detach_buffer(z);
1765
+ }
1766
+
1767
+ /*
1768
+ * Document-method: Zstdlib::Deflate.params
1769
+ *
1770
+ * call-seq: params(level, strategy)
1771
+ *
1772
+ * Changes the parameters of the deflate stream to allow changes between
1773
+ * different types of data that require different types of compression. Any
1774
+ * unprocessed data is flushed before changing the params.
1775
+ *
1776
+ * See Zstdlib::Deflate.new for a description of +level+ and +strategy+.
1777
+ *
1778
+ */
1779
+ static VALUE
1780
+ rb_deflate_params(VALUE obj, VALUE v_level, VALUE v_strategy)
1781
+ {
1782
+ struct zstream *z = get_zstream(obj);
1783
+ int level, strategy;
1784
+ int err;
1785
+ uInt n;
1786
+ long filled;
1787
+
1788
+ level = ARG_LEVEL(v_level);
1789
+ strategy = ARG_STRATEGY(v_strategy);
1790
+
1791
+ n = z->stream.avail_out;
1792
+ err = deflateParams(&z->stream, level, strategy);
1793
+ filled = n - z->stream.avail_out;
1794
+ while (err == Z_BUF_ERROR) {
1795
+ rb_warning("deflateParams() returned Z_BUF_ERROR");
1796
+ zstream_expand_buffer(z);
1797
+ rb_str_set_len(z->buf, RSTRING_LEN(z->buf) + filled);
1798
+ n = z->stream.avail_out;
1799
+ err = deflateParams(&z->stream, level, strategy);
1800
+ filled = n - z->stream.avail_out;
1801
+ }
1802
+ if (err != Z_OK) {
1803
+ raise_zlib_error(err, z->stream.msg);
1804
+ }
1805
+ rb_str_set_len(z->buf, RSTRING_LEN(z->buf) + filled);
1806
+
1807
+ return Qnil;
1808
+ }
1809
+
1810
+ /*
1811
+ * Document-method: Zstdlib::Deflate.set_dictionary
1812
+ *
1813
+ * call-seq: set_dictionary(string)
1814
+ *
1815
+ * Sets the preset dictionary and returns +string+. This method is available
1816
+ * just only after Zstdlib::Deflate.new or Zstdlib::ZStream#reset method was called.
1817
+ * See zlib.h for details.
1818
+ *
1819
+ * Can raise errors of Z_STREAM_ERROR if a parameter is invalid (such as
1820
+ * NULL dictionary) or the stream state is inconsistent, Z_DATA_ERROR if
1821
+ * the given dictionary doesn't match the expected one (incorrect adler32 value)
1822
+ *
1823
+ */
1824
+ static VALUE
1825
+ rb_deflate_set_dictionary(VALUE obj, VALUE dic)
1826
+ {
1827
+ struct zstream *z = get_zstream(obj);
1828
+ VALUE src = dic;
1829
+ int err;
1830
+
1831
+ StringValue(src);
1832
+ err = deflateSetDictionary(&z->stream,
1833
+ (Bytef*)RSTRING_PTR(src), RSTRING_LENINT(src));
1834
+ if (err != Z_OK) {
1835
+ raise_zlib_error(err, z->stream.msg);
1836
+ }
1837
+
1838
+ return dic;
1839
+ }
1840
+
1841
+
1842
+ /* ------------------------------------------------------------------------- */
1843
+
1844
+ /*
1845
+ * Document-class: Zstdlib::Inflate
1846
+ *
1847
+ * Zlib:Inflate is the class for decompressing compressed data. Unlike
1848
+ * Zstdlib::Deflate, an instance of this class is not able to duplicate (clone,
1849
+ * dup) itself.
1850
+ */
1851
+
1852
+ static VALUE
1853
+ rb_inflate_s_allocate(VALUE klass)
1854
+ {
1855
+ VALUE inflate = zstream_inflate_new(klass);
1856
+ rb_ivar_set(inflate, id_dictionaries, rb_hash_new());
1857
+ return inflate;
1858
+ }
1859
+
1860
+ /*
1861
+ * Document-method: Zstdlib::Inflate.new
1862
+ *
1863
+ * call-seq:
1864
+ * Zstdlib::Inflate.new(window_bits = Zstdlib::MAX_WBITS)
1865
+ *
1866
+ * Creates a new inflate stream for decompression. +window_bits+ sets the
1867
+ * size of the history buffer and can have the following values:
1868
+ *
1869
+ * 0::
1870
+ * Have inflate use the window size from the zlib header of the compressed
1871
+ * stream.
1872
+ *
1873
+ * (8..15)::
1874
+ * Overrides the window size of the inflate header in the compressed stream.
1875
+ * The window size must be greater than or equal to the window size of the
1876
+ * compressed stream.
1877
+ *
1878
+ * Greater than 15::
1879
+ * Add 32 to window_bits to enable zlib and gzip decoding with automatic
1880
+ * header detection, or add 16 to decode only the gzip format (a
1881
+ * Zstdlib::DataError will be raised for a non-gzip stream).
1882
+ *
1883
+ * (-8..-15)::
1884
+ * Enables raw deflate mode which will not generate a check value, and will
1885
+ * not look for any check values for comparison at the end of the stream.
1886
+ *
1887
+ * This is for use with other formats that use the deflate compressed data
1888
+ * format such as zip which provide their own check values.
1889
+ *
1890
+ * == Example
1891
+ *
1892
+ * open "compressed.file" do |compressed_io|
1893
+ * zi = Zstdlib::Inflate.new(Zstdlib::MAX_WBITS + 32)
1894
+ *
1895
+ * begin
1896
+ * open "uncompressed.file", "w+" do |uncompressed_io|
1897
+ * uncompressed_io << zi.inflate(compressed_io.read)
1898
+ * end
1899
+ * ensure
1900
+ * zi.close
1901
+ * end
1902
+ * end
1903
+ *
1904
+ */
1905
+ static VALUE
1906
+ rb_inflate_initialize(int argc, VALUE *argv, VALUE obj)
1907
+ {
1908
+ struct zstream *z;
1909
+ VALUE wbits;
1910
+ int err;
1911
+
1912
+ rb_scan_args(argc, argv, "01", &wbits);
1913
+ TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z);
1914
+
1915
+ err = inflateInit2(&z->stream, ARG_WBITS(wbits));
1916
+ if (err != Z_OK) {
1917
+ raise_zlib_error(err, z->stream.msg);
1918
+ }
1919
+ ZSTREAM_READY(z);
1920
+
1921
+ return obj;
1922
+ }
1923
+
1924
+ static VALUE
1925
+ inflate_run(VALUE args)
1926
+ {
1927
+ struct zstream *z = (struct zstream*)((VALUE*)args)[0];
1928
+ VALUE src = ((VALUE*)args)[1];
1929
+
1930
+ zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), Z_SYNC_FLUSH);
1931
+ zstream_run(z, (Bytef*)"", 0, Z_FINISH); /* for checking errors */
1932
+ return zstream_detach_buffer(z);
1933
+ }
1934
+
1935
+ /*
1936
+ * Document-method: Zstdlib::inflate
1937
+ *
1938
+ * call-seq:
1939
+ * Zstdlib.inflate(string)
1940
+ * Zstdlib::Inflate.inflate(string)
1941
+ *
1942
+ * Decompresses +string+. Raises a Zstdlib::NeedDict exception if a preset
1943
+ * dictionary is needed for decompression.
1944
+ *
1945
+ * This method is almost equivalent to the following code:
1946
+ *
1947
+ * def inflate(string)
1948
+ * zstream = Zstdlib::Inflate.new
1949
+ * buf = zstream.inflate(string)
1950
+ * zstream.finish
1951
+ * zstream.close
1952
+ * buf
1953
+ * end
1954
+ *
1955
+ * See also Zstdlib.deflate
1956
+ *
1957
+ */
1958
+ static VALUE
1959
+ rb_inflate_s_inflate(VALUE obj, VALUE src)
1960
+ {
1961
+ struct zstream z;
1962
+ VALUE dst, args[2];
1963
+ int err;
1964
+
1965
+ StringValue(src);
1966
+ zstream_init_inflate(&z);
1967
+ err = inflateInit(&z.stream);
1968
+ if (err != Z_OK) {
1969
+ raise_zlib_error(err, z.stream.msg);
1970
+ }
1971
+ ZSTREAM_READY(&z);
1972
+
1973
+ args[0] = (VALUE)&z;
1974
+ args[1] = src;
1975
+ dst = rb_ensure(inflate_run, (VALUE)args, zstream_ensure_end, (VALUE)&z);
1976
+
1977
+ return dst;
1978
+ }
1979
+
1980
+ static void
1981
+ do_inflate(struct zstream *z, VALUE src)
1982
+ {
1983
+ if (NIL_P(src)) {
1984
+ zstream_run(z, (Bytef*)"", 0, Z_FINISH);
1985
+ return;
1986
+ }
1987
+ StringValue(src);
1988
+ if (RSTRING_LEN(src) > 0 || z->stream.avail_in > 0) { /* prevent Z_BUF_ERROR */
1989
+ zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), Z_SYNC_FLUSH);
1990
+ }
1991
+ }
1992
+
1993
+ /* Document-method: Zstdlib::Inflate#add_dictionary
1994
+ *
1995
+ * call-seq: add_dictionary(string)
1996
+ *
1997
+ * Provide the inflate stream with a dictionary that may be required in the
1998
+ * future. Multiple dictionaries may be provided. The inflate stream will
1999
+ * automatically choose the correct user-provided dictionary based on the
2000
+ * stream's required dictionary.
2001
+ */
2002
+ static VALUE
2003
+ rb_inflate_add_dictionary(VALUE obj, VALUE dictionary)
2004
+ {
2005
+ VALUE dictionaries = rb_ivar_get(obj, id_dictionaries);
2006
+ VALUE checksum = do_checksum(1, &dictionary, adler32);
2007
+
2008
+ rb_hash_aset(dictionaries, checksum, dictionary);
2009
+
2010
+ return obj;
2011
+ }
2012
+
2013
+ /*
2014
+ * Document-method: Zstdlib::Inflate#inflate
2015
+ *
2016
+ * call-seq:
2017
+ * inflate(deflate_string) -> String
2018
+ * inflate(deflate_string) { |chunk| ... } -> nil
2019
+ *
2020
+ * Inputs +deflate_string+ into the inflate stream and returns the output from
2021
+ * the stream. Calling this method, both the input and the output buffer of
2022
+ * the stream are flushed. If string is +nil+, this method finishes the
2023
+ * stream, just like Zstdlib::ZStream#finish.
2024
+ *
2025
+ * If a block is given consecutive inflated chunks from the +deflate_string+
2026
+ * are yielded to the block and +nil+ is returned.
2027
+ *
2028
+ * Raises a Zstdlib::NeedDict exception if a preset dictionary is needed to
2029
+ * decompress. Set the dictionary by Zstdlib::Inflate#set_dictionary and then
2030
+ * call this method again with an empty string to flush the stream:
2031
+ *
2032
+ * inflater = Zstdlib::Inflate.new
2033
+ *
2034
+ * begin
2035
+ * out = inflater.inflate compressed
2036
+ * rescue Zstdlib::NeedDict
2037
+ * # ensure the dictionary matches the stream's required dictionary
2038
+ * raise unless inflater.adler == Zstdlib.adler32(dictionary)
2039
+ *
2040
+ * inflater.set_dictionary dictionary
2041
+ * inflater.inflate ''
2042
+ * end
2043
+ *
2044
+ * # ...
2045
+ *
2046
+ * inflater.close
2047
+ *
2048
+ * See also Zstdlib::Inflate.new
2049
+ */
2050
+ static VALUE
2051
+ rb_inflate_inflate(VALUE obj, VALUE src)
2052
+ {
2053
+ struct zstream *z = get_zstream(obj);
2054
+ VALUE dst;
2055
+
2056
+ if (ZSTREAM_IS_FINISHED(z)) {
2057
+ if (NIL_P(src)) {
2058
+ dst = zstream_detach_buffer(z);
2059
+ }
2060
+ else {
2061
+ StringValue(src);
2062
+ zstream_append_buffer2(z, src);
2063
+ dst = rb_str_new(0, 0);
2064
+ }
2065
+ }
2066
+ else {
2067
+ do_inflate(z, src);
2068
+ dst = zstream_detach_buffer(z);
2069
+ if (ZSTREAM_IS_FINISHED(z)) {
2070
+ zstream_passthrough_input(z);
2071
+ }
2072
+ }
2073
+
2074
+ return dst;
2075
+ }
2076
+
2077
+ /*
2078
+ * call-seq: << string
2079
+ *
2080
+ * Inputs +string+ into the inflate stream just like Zstdlib::Inflate#inflate, but
2081
+ * returns the Zstdlib::Inflate object itself. The output from the stream is
2082
+ * preserved in output buffer.
2083
+ */
2084
+ static VALUE
2085
+ rb_inflate_addstr(VALUE obj, VALUE src)
2086
+ {
2087
+ struct zstream *z = get_zstream(obj);
2088
+
2089
+ if (ZSTREAM_IS_FINISHED(z)) {
2090
+ if (!NIL_P(src)) {
2091
+ StringValue(src);
2092
+ zstream_append_buffer2(z, src);
2093
+ }
2094
+ }
2095
+ else {
2096
+ do_inflate(z, src);
2097
+ if (ZSTREAM_IS_FINISHED(z)) {
2098
+ zstream_passthrough_input(z);
2099
+ }
2100
+ }
2101
+
2102
+ return obj;
2103
+ }
2104
+
2105
+ /*
2106
+ * call-seq: sync(string)
2107
+ *
2108
+ * Inputs +string+ into the end of input buffer and skips data until a full
2109
+ * flush point can be found. If the point is found in the buffer, this method
2110
+ * flushes the buffer and returns false. Otherwise it returns +true+ and the
2111
+ * following data of full flush point is preserved in the buffer.
2112
+ */
2113
+ static VALUE
2114
+ rb_inflate_sync(VALUE obj, VALUE src)
2115
+ {
2116
+ struct zstream *z = get_zstream(obj);
2117
+
2118
+ StringValue(src);
2119
+ return zstream_sync(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src));
2120
+ }
2121
+
2122
+ /*
2123
+ * Quoted verbatim from original documentation:
2124
+ *
2125
+ * What is this?
2126
+ *
2127
+ * <tt>:)</tt>
2128
+ */
2129
+ static VALUE
2130
+ rb_inflate_sync_point_p(VALUE obj)
2131
+ {
2132
+ struct zstream *z = get_zstream(obj);
2133
+ int err;
2134
+
2135
+ err = inflateSyncPoint(&z->stream);
2136
+ if (err == 1) {
2137
+ return Qtrue;
2138
+ }
2139
+ if (err != Z_OK) {
2140
+ raise_zlib_error(err, z->stream.msg);
2141
+ }
2142
+ return Qfalse;
2143
+ }
2144
+
2145
+ /*
2146
+ * Document-method: Zstdlib::Inflate#set_dictionary
2147
+ *
2148
+ * Sets the preset dictionary and returns +string+. This method is available just
2149
+ * only after a Zstdlib::NeedDict exception was raised. See zlib.h for details.
2150
+ *
2151
+ */
2152
+ static VALUE
2153
+ rb_inflate_set_dictionary(VALUE obj, VALUE dic)
2154
+ {
2155
+ struct zstream *z = get_zstream(obj);
2156
+ VALUE src = dic;
2157
+ int err;
2158
+
2159
+ StringValue(src);
2160
+ err = inflateSetDictionary(&z->stream,
2161
+ (Bytef*)RSTRING_PTR(src), RSTRING_LENINT(src));
2162
+ if (err != Z_OK) {
2163
+ raise_zlib_error(err, z->stream.msg);
2164
+ }
2165
+
2166
+ return dic;
2167
+ }
2168
+
2169
+
2170
+
2171
+ #if GZIP_SUPPORT
2172
+
2173
+ /* NOTE: Features for gzip files of Ruby/zlib are written from scratch
2174
+ * and using undocumented feature of zlib, negative wbits.
2175
+ * I don't think gzFile APIs of zlib are good for Ruby.
2176
+ */
2177
+
2178
+ /*------- .gz file header --------*/
2179
+
2180
+ #define GZ_MAGIC1 0x1f
2181
+ #define GZ_MAGIC2 0x8b
2182
+ #define GZ_METHOD_DEFLATE 8
2183
+ #define GZ_FLAG_MULTIPART 0x2
2184
+ #define GZ_FLAG_EXTRA 0x4
2185
+ #define GZ_FLAG_ORIG_NAME 0x8
2186
+ #define GZ_FLAG_COMMENT 0x10
2187
+ #define GZ_FLAG_ENCRYPT 0x20
2188
+ #define GZ_FLAG_UNKNOWN_MASK 0xc0
2189
+
2190
+ #define GZ_EXTRAFLAG_FAST 0x4
2191
+ #define GZ_EXTRAFLAG_SLOW 0x2
2192
+
2193
+ /* from zutil.h */
2194
+ #define OS_MSDOS 0x00
2195
+ #define OS_AMIGA 0x01
2196
+ #define OS_VMS 0x02
2197
+ #define OS_UNIX 0x03
2198
+ #define OS_ATARI 0x05
2199
+ #define OS_OS2 0x06
2200
+ #define OS_MACOS 0x07
2201
+ #define OS_TOPS20 0x0a
2202
+ #define OS_WIN32 0x0b
2203
+
2204
+ #define OS_VMCMS 0x04
2205
+ #define OS_ZSYSTEM 0x08
2206
+ #define OS_CPM 0x09
2207
+ #define OS_QDOS 0x0c
2208
+ #define OS_RISCOS 0x0d
2209
+ #define OS_UNKNOWN 0xff
2210
+
2211
+ #ifndef OS_CODE
2212
+ #define OS_CODE OS_UNIX
2213
+ #endif
2214
+
2215
+ static ID id_write, id_read, id_readpartial, id_flush, id_seek, id_close, id_path, id_input;
2216
+ static VALUE cGzError, cNoFooter, cCRCError, cLengthError;
2217
+
2218
+
2219
+
2220
+ /*-------- gzfile internal APIs --------*/
2221
+
2222
+ struct gzfile {
2223
+ struct zstream z;
2224
+ VALUE io;
2225
+ int level;
2226
+ int os_code; /* for header */
2227
+ time_t mtime; /* for header */
2228
+ VALUE orig_name; /* for header; must be a String */
2229
+ VALUE comment; /* for header; must be a String */
2230
+ unsigned long crc;
2231
+ int ecflags;
2232
+ int lineno;
2233
+ long ungetc;
2234
+ void (*end)(struct gzfile *);
2235
+ rb_encoding *enc;
2236
+ rb_encoding *enc2;
2237
+ rb_econv_t *ec;
2238
+ VALUE ecopts;
2239
+ VALUE path;
2240
+ };
2241
+ #define GZFILE_CBUF_CAPA 10
2242
+
2243
+ #define GZFILE_FLAG_SYNC ZSTREAM_FLAG_UNUSED
2244
+ #define GZFILE_FLAG_HEADER_FINISHED (ZSTREAM_FLAG_UNUSED << 1)
2245
+ #define GZFILE_FLAG_FOOTER_FINISHED (ZSTREAM_FLAG_UNUSED << 2)
2246
+ #define GZFILE_FLAG_MTIME_IS_SET (ZSTREAM_FLAG_UNUSED << 3)
2247
+
2248
+ #define GZFILE_IS_FINISHED(gz) \
2249
+ (ZSTREAM_IS_FINISHED(&(gz)->z) && ZSTREAM_BUF_FILLED(&(gz)->z) == 0)
2250
+
2251
+ #define GZFILE_READ_SIZE 2048
2252
+
2253
+ struct read_raw_arg {
2254
+ VALUE io;
2255
+ union {
2256
+ const VALUE argv[2]; /* for rb_funcallv */
2257
+ struct {
2258
+ VALUE len;
2259
+ VALUE buf;
2260
+ } in;
2261
+ } as;
2262
+ };
2263
+
2264
+ static void
2265
+ gzfile_mark(void *p)
2266
+ {
2267
+ struct gzfile *gz = p;
2268
+
2269
+ rb_gc_mark(gz->io);
2270
+ rb_gc_mark(gz->orig_name);
2271
+ rb_gc_mark(gz->comment);
2272
+ zstream_mark(&gz->z);
2273
+ rb_gc_mark(gz->ecopts);
2274
+ rb_gc_mark(gz->path);
2275
+ }
2276
+
2277
+ static void
2278
+ gzfile_free(void *p)
2279
+ {
2280
+ struct gzfile *gz = p;
2281
+ struct zstream *z = &gz->z;
2282
+
2283
+ if (ZSTREAM_IS_READY(z)) {
2284
+ if (z->func == &deflate_funcs) {
2285
+ finalizer_warn("Zstdlib::GzipWriter object must be closed explicitly.");
2286
+ }
2287
+ zstream_finalize(z);
2288
+ }
2289
+ xfree(gz);
2290
+ }
2291
+
2292
+ static size_t
2293
+ gzfile_memsize(const void *p)
2294
+ {
2295
+ return sizeof(struct gzfile);
2296
+ }
2297
+
2298
+ static const rb_data_type_t gzfile_data_type = {
2299
+ "gzfile",
2300
+ { gzfile_mark, gzfile_free, gzfile_memsize, },
2301
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
2302
+ };
2303
+
2304
+ static void
2305
+ gzfile_init(struct gzfile *gz, const struct zstream_funcs *funcs, void (*endfunc)(struct gzfile *))
2306
+ {
2307
+ zstream_init(&gz->z, funcs);
2308
+ gz->z.flags |= ZSTREAM_FLAG_GZFILE;
2309
+ gz->io = Qnil;
2310
+ gz->level = 0;
2311
+ gz->mtime = 0;
2312
+ gz->os_code = OS_CODE;
2313
+ gz->orig_name = Qnil;
2314
+ gz->comment = Qnil;
2315
+ gz->crc = crc32(0, Z_NULL, 0);
2316
+ gz->lineno = 0;
2317
+ gz->ungetc = 0;
2318
+ gz->end = endfunc;
2319
+ gz->enc = rb_default_external_encoding();
2320
+ gz->enc2 = 0;
2321
+ gz->ec = NULL;
2322
+ gz->ecflags = 0;
2323
+ gz->ecopts = Qnil;
2324
+ gz->path = Qnil;
2325
+ }
2326
+
2327
+ static VALUE
2328
+ gzfile_new(VALUE klass, const struct zstream_funcs *funcs, void (*endfunc)(struct gzfile *))
2329
+ {
2330
+ VALUE obj;
2331
+ struct gzfile *gz;
2332
+
2333
+ obj = TypedData_Make_Struct(klass, struct gzfile, &gzfile_data_type, gz);
2334
+ gzfile_init(gz, funcs, endfunc);
2335
+ return obj;
2336
+ }
2337
+
2338
+ #define gzfile_writer_new(gz) gzfile_new((gz),&deflate_funcs,gzfile_writer_end)
2339
+ #define gzfile_reader_new(gz) gzfile_new((gz),&inflate_funcs,gzfile_reader_end)
2340
+
2341
+ static void
2342
+ gzfile_reset(struct gzfile *gz)
2343
+ {
2344
+ zstream_reset(&gz->z);
2345
+ gz->z.flags |= ZSTREAM_FLAG_GZFILE;
2346
+ gz->crc = crc32(0, Z_NULL, 0);
2347
+ gz->lineno = 0;
2348
+ gz->ungetc = 0;
2349
+ if (gz->ec) {
2350
+ rb_econv_close(gz->ec);
2351
+ gz->ec = rb_econv_open_opts(gz->enc2->name, gz->enc->name,
2352
+ gz->ecflags, gz->ecopts);
2353
+ }
2354
+ }
2355
+
2356
+ static void
2357
+ gzfile_close(struct gzfile *gz, int closeflag)
2358
+ {
2359
+ VALUE io = gz->io;
2360
+
2361
+ gz->end(gz);
2362
+ gz->io = Qnil;
2363
+ gz->orig_name = Qnil;
2364
+ gz->comment = Qnil;
2365
+ if (closeflag && rb_respond_to(io, id_close)) {
2366
+ rb_funcall(io, id_close, 0);
2367
+ }
2368
+ }
2369
+
2370
+ static void
2371
+ gzfile_write_raw(struct gzfile *gz)
2372
+ {
2373
+ VALUE str;
2374
+
2375
+ if (ZSTREAM_BUF_FILLED(&gz->z) > 0) {
2376
+ str = zstream_detach_buffer(&gz->z);
2377
+ rb_funcall(gz->io, id_write, 1, str);
2378
+ if ((gz->z.flags & GZFILE_FLAG_SYNC)
2379
+ && rb_respond_to(gz->io, id_flush))
2380
+ rb_funcall(gz->io, id_flush, 0);
2381
+ }
2382
+ }
2383
+
2384
+ static VALUE
2385
+ gzfile_read_raw_partial(VALUE arg)
2386
+ {
2387
+ struct read_raw_arg *ra = (struct read_raw_arg *)arg;
2388
+ VALUE str;
2389
+ int argc = NIL_P(ra->as.argv[1]) ? 1 : 2;
2390
+
2391
+ str = rb_funcallv(ra->io, id_readpartial, argc, ra->as.argv);
2392
+ Check_Type(str, T_STRING);
2393
+ return str;
2394
+ }
2395
+
2396
+ static VALUE
2397
+ gzfile_read_raw_rescue(VALUE arg, VALUE _)
2398
+ {
2399
+ struct read_raw_arg *ra = (struct read_raw_arg *)arg;
2400
+ VALUE str = Qnil;
2401
+ if (rb_obj_is_kind_of(rb_errinfo(), rb_eNoMethodError)) {
2402
+ int argc = NIL_P(ra->as.argv[1]) ? 1 : 2;
2403
+ str = rb_funcallv(ra->io, id_read, argc, ra->as.argv);
2404
+ if (!NIL_P(str)) {
2405
+ Check_Type(str, T_STRING);
2406
+ }
2407
+ }
2408
+ return str; /* return nil when EOFError */
2409
+ }
2410
+
2411
+ static VALUE
2412
+ gzfile_read_raw(struct gzfile *gz, VALUE outbuf)
2413
+ {
2414
+ struct read_raw_arg ra;
2415
+
2416
+ ra.io = gz->io;
2417
+ ra.as.in.len = INT2FIX(GZFILE_READ_SIZE);
2418
+ ra.as.in.buf = outbuf;
2419
+
2420
+ return rb_rescue2(gzfile_read_raw_partial, (VALUE)&ra,
2421
+ gzfile_read_raw_rescue, (VALUE)&ra,
2422
+ rb_eEOFError, rb_eNoMethodError, (VALUE)0);
2423
+ }
2424
+
2425
+ static int
2426
+ gzfile_read_raw_ensure(struct gzfile *gz, long size, VALUE outbuf)
2427
+ {
2428
+ VALUE str;
2429
+
2430
+ if (gz->io == Qundef) { /* Zstdlib.gunzip */
2431
+ if (NIL_P(gz->z.input) || RSTRING_LEN(gz->z.input) < size)
2432
+ rb_raise(cGzError, "unexpected end of string");
2433
+ }
2434
+ while (NIL_P(gz->z.input) || RSTRING_LEN(gz->z.input) < size) {
2435
+ str = gzfile_read_raw(gz, outbuf);
2436
+ if (NIL_P(str)) return 0;
2437
+ zstream_append_input2(&gz->z, str);
2438
+ }
2439
+ return 1;
2440
+ }
2441
+
2442
+ static char *
2443
+ gzfile_read_raw_until_zero(struct gzfile *gz, long offset)
2444
+ {
2445
+ VALUE str;
2446
+ char *p;
2447
+
2448
+ for (;;) {
2449
+ p = memchr(RSTRING_PTR(gz->z.input) + offset, '\0',
2450
+ RSTRING_LEN(gz->z.input) - offset);
2451
+ if (p) break;
2452
+ str = gzfile_read_raw(gz, Qnil);
2453
+ if (NIL_P(str)) {
2454
+ rb_raise(cGzError, "unexpected end of file");
2455
+ }
2456
+ offset = RSTRING_LEN(gz->z.input);
2457
+ zstream_append_input2(&gz->z, str);
2458
+ }
2459
+ return p;
2460
+ }
2461
+
2462
+ static unsigned int
2463
+ gzfile_get16(const unsigned char *src)
2464
+ {
2465
+ unsigned int n;
2466
+ n = *(src++) & 0xff;
2467
+ n |= (*(src++) & 0xff) << 8;
2468
+ return n;
2469
+ }
2470
+
2471
+ static unsigned long
2472
+ gzfile_get32(const unsigned char *src)
2473
+ {
2474
+ unsigned long n;
2475
+ n = *(src++) & 0xff;
2476
+ n |= (*(src++) & 0xff) << 8;
2477
+ n |= (*(src++) & 0xff) << 16;
2478
+ n |= (*(src++) & 0xffU) << 24;
2479
+ return n;
2480
+ }
2481
+
2482
+ static void
2483
+ gzfile_set32(unsigned long n, unsigned char *dst)
2484
+ {
2485
+ *(dst++) = n & 0xff;
2486
+ *(dst++) = (n >> 8) & 0xff;
2487
+ *(dst++) = (n >> 16) & 0xff;
2488
+ *dst = (n >> 24) & 0xff;
2489
+ }
2490
+
2491
+ static void
2492
+ gzfile_raise(struct gzfile *gz, VALUE klass, const char *message)
2493
+ {
2494
+ VALUE exc = rb_exc_new2(klass, message);
2495
+ if (!NIL_P(gz->z.input)) {
2496
+ rb_ivar_set(exc, id_input, rb_str_resurrect(gz->z.input));
2497
+ }
2498
+ rb_exc_raise(exc);
2499
+ }
2500
+
2501
+ /*
2502
+ * Document-method: Zstdlib::GzipFile::Error#inspect
2503
+ *
2504
+ * Constructs a String of the GzipFile Error
2505
+ */
2506
+ static VALUE
2507
+ gzfile_error_inspect(VALUE error)
2508
+ {
2509
+ VALUE str = rb_call_super(0, 0);
2510
+ VALUE input = rb_attr_get(error, id_input);
2511
+
2512
+ if (!NIL_P(input)) {
2513
+ rb_str_resize(str, RSTRING_LEN(str)-1);
2514
+ rb_str_cat2(str, ", input=");
2515
+ rb_str_append(str, rb_str_inspect(input));
2516
+ rb_str_cat2(str, ">");
2517
+ }
2518
+ return str;
2519
+ }
2520
+
2521
+ static void
2522
+ gzfile_make_header(struct gzfile *gz)
2523
+ {
2524
+ Bytef buf[10]; /* the size of gzip header */
2525
+ unsigned char flags = 0, extraflags = 0;
2526
+
2527
+ if (!NIL_P(gz->orig_name)) {
2528
+ flags |= GZ_FLAG_ORIG_NAME;
2529
+ }
2530
+ if (!NIL_P(gz->comment)) {
2531
+ flags |= GZ_FLAG_COMMENT;
2532
+ }
2533
+ if (!(gz->z.flags & GZFILE_FLAG_MTIME_IS_SET)) {
2534
+ gz->mtime = time(0);
2535
+ }
2536
+
2537
+ if (gz->level == Z_BEST_SPEED) {
2538
+ extraflags |= GZ_EXTRAFLAG_FAST;
2539
+ }
2540
+ else if (gz->level == ZSTD_maxCLevel()) {
2541
+ extraflags |= GZ_EXTRAFLAG_SLOW;
2542
+ }
2543
+
2544
+ buf[0] = GZ_MAGIC1;
2545
+ buf[1] = GZ_MAGIC2;
2546
+ buf[2] = GZ_METHOD_DEFLATE;
2547
+ buf[3] = flags;
2548
+ gzfile_set32((unsigned long)gz->mtime, &buf[4]);
2549
+ buf[8] = extraflags;
2550
+ buf[9] = gz->os_code;
2551
+ zstream_append_buffer(&gz->z, buf, (long)sizeof(buf));
2552
+
2553
+ if (!NIL_P(gz->orig_name)) {
2554
+ zstream_append_buffer2(&gz->z, gz->orig_name);
2555
+ zstream_append_buffer(&gz->z, (Bytef*)"\0", 1);
2556
+ }
2557
+ if (!NIL_P(gz->comment)) {
2558
+ zstream_append_buffer2(&gz->z, gz->comment);
2559
+ zstream_append_buffer(&gz->z, (Bytef*)"\0", 1);
2560
+ }
2561
+
2562
+ gz->z.flags |= GZFILE_FLAG_HEADER_FINISHED;
2563
+ }
2564
+
2565
+ static void
2566
+ gzfile_make_footer(struct gzfile *gz)
2567
+ {
2568
+ Bytef buf[8]; /* 8 is the size of gzip footer */
2569
+
2570
+ gzfile_set32(gz->crc, buf);
2571
+ gzfile_set32(gz->z.stream.total_in, &buf[4]);
2572
+ zstream_append_buffer(&gz->z, buf, (long)sizeof(buf));
2573
+ gz->z.flags |= GZFILE_FLAG_FOOTER_FINISHED;
2574
+ }
2575
+
2576
+ static void
2577
+ gzfile_read_header(struct gzfile *gz, VALUE outbuf)
2578
+ {
2579
+ const unsigned char *head;
2580
+ long len;
2581
+ char flags, *p;
2582
+
2583
+ /* 10 is the size of gzip header */
2584
+ if (!gzfile_read_raw_ensure(gz, 10, outbuf)) {
2585
+ gzfile_raise(gz, cGzError, "not in gzip format");
2586
+ }
2587
+
2588
+ head = (unsigned char*)RSTRING_PTR(gz->z.input);
2589
+
2590
+ if (head[0] != GZ_MAGIC1 || head[1] != GZ_MAGIC2) {
2591
+ gzfile_raise(gz, cGzError, "not in gzip format");
2592
+ }
2593
+ if (head[2] != GZ_METHOD_DEFLATE) {
2594
+ rb_raise(cGzError, "unsupported compression method %d", head[2]);
2595
+ }
2596
+
2597
+ flags = head[3];
2598
+ if (flags & GZ_FLAG_MULTIPART) {
2599
+ rb_raise(cGzError, "multi-part gzip file is not supported");
2600
+ }
2601
+ else if (flags & GZ_FLAG_ENCRYPT) {
2602
+ rb_raise(cGzError, "encrypted gzip file is not supported");
2603
+ }
2604
+ else if (flags & GZ_FLAG_UNKNOWN_MASK) {
2605
+ rb_raise(cGzError, "unknown flags 0x%02x", flags);
2606
+ }
2607
+
2608
+ if (head[8] & GZ_EXTRAFLAG_FAST) {
2609
+ gz->level = Z_BEST_SPEED;
2610
+ }
2611
+ else if (head[8] & GZ_EXTRAFLAG_SLOW) {
2612
+ gz->level = ZSTD_maxCLevel();
2613
+ }
2614
+ else {
2615
+ gz->level = ZSTD_CLEVEL_DEFAULT;
2616
+ }
2617
+
2618
+ gz->mtime = gzfile_get32(&head[4]);
2619
+ gz->os_code = head[9];
2620
+ zstream_discard_input(&gz->z, 10);
2621
+
2622
+ if (flags & GZ_FLAG_EXTRA) {
2623
+ if (!gzfile_read_raw_ensure(gz, 2, outbuf)) {
2624
+ rb_raise(cGzError, "unexpected end of file");
2625
+ }
2626
+ len = gzfile_get16((Bytef*)RSTRING_PTR(gz->z.input));
2627
+ if (!gzfile_read_raw_ensure(gz, 2 + len, outbuf)) {
2628
+ rb_raise(cGzError, "unexpected end of file");
2629
+ }
2630
+ zstream_discard_input(&gz->z, 2 + len);
2631
+ }
2632
+ if (flags & GZ_FLAG_ORIG_NAME) {
2633
+ if (!gzfile_read_raw_ensure(gz, 1, outbuf)) {
2634
+ rb_raise(cGzError, "unexpected end of file");
2635
+ }
2636
+ p = gzfile_read_raw_until_zero(gz, 0);
2637
+ len = p - RSTRING_PTR(gz->z.input);
2638
+ gz->orig_name = rb_str_new(RSTRING_PTR(gz->z.input), len);
2639
+ zstream_discard_input(&gz->z, len + 1);
2640
+ }
2641
+ if (flags & GZ_FLAG_COMMENT) {
2642
+ if (!gzfile_read_raw_ensure(gz, 1, outbuf)) {
2643
+ rb_raise(cGzError, "unexpected end of file");
2644
+ }
2645
+ p = gzfile_read_raw_until_zero(gz, 0);
2646
+ len = p - RSTRING_PTR(gz->z.input);
2647
+ gz->comment = rb_str_new(RSTRING_PTR(gz->z.input), len);
2648
+ zstream_discard_input(&gz->z, len + 1);
2649
+ }
2650
+
2651
+ if (gz->z.input != Qnil && RSTRING_LEN(gz->z.input) > 0) {
2652
+ zstream_run(&gz->z, 0, 0, Z_SYNC_FLUSH);
2653
+ }
2654
+ }
2655
+
2656
+ static void
2657
+ gzfile_check_footer(struct gzfile *gz, VALUE outbuf)
2658
+ {
2659
+ unsigned long crc, length;
2660
+
2661
+ gz->z.flags |= GZFILE_FLAG_FOOTER_FINISHED;
2662
+
2663
+ /* 8 is the size of gzip footer */
2664
+ if (!gzfile_read_raw_ensure(gz, 8, outbuf)) {
2665
+ gzfile_raise(gz, cNoFooter, "footer is not found");
2666
+ }
2667
+
2668
+ crc = gzfile_get32((Bytef*)RSTRING_PTR(gz->z.input));
2669
+ length = gzfile_get32((Bytef*)RSTRING_PTR(gz->z.input) + 4);
2670
+
2671
+ gz->z.stream.total_in += 8; /* to rewind correctly */
2672
+ zstream_discard_input(&gz->z, 8);
2673
+
2674
+ if (gz->crc != crc) {
2675
+ rb_raise(cCRCError, "invalid compressed data -- crc error");
2676
+ }
2677
+ if ((uint32_t)gz->z.stream.total_out != length) {
2678
+ rb_raise(cLengthError, "invalid compressed data -- length error");
2679
+ }
2680
+ }
2681
+
2682
+ static void
2683
+ gzfile_write(struct gzfile *gz, Bytef *str, long len)
2684
+ {
2685
+ if (!(gz->z.flags & GZFILE_FLAG_HEADER_FINISHED)) {
2686
+ gzfile_make_header(gz);
2687
+ }
2688
+
2689
+ if (len > 0 || (gz->z.flags & GZFILE_FLAG_SYNC)) {
2690
+ gz->crc = checksum_long(crc32, gz->crc, str, len);
2691
+ zstream_run(&gz->z, str, len, (gz->z.flags & GZFILE_FLAG_SYNC)
2692
+ ? Z_SYNC_FLUSH : Z_NO_FLUSH);
2693
+ }
2694
+ gzfile_write_raw(gz);
2695
+ }
2696
+
2697
+ static long
2698
+ gzfile_read_more(struct gzfile *gz, VALUE outbuf)
2699
+ {
2700
+ VALUE str;
2701
+
2702
+ while (!ZSTREAM_IS_FINISHED(&gz->z)) {
2703
+ str = gzfile_read_raw(gz, outbuf);
2704
+ if (NIL_P(str)) {
2705
+ if (!ZSTREAM_IS_FINISHED(&gz->z)) {
2706
+ rb_raise(cGzError, "unexpected end of file");
2707
+ }
2708
+ break;
2709
+ }
2710
+ if (RSTRING_LEN(str) > 0) { /* prevent Z_BUF_ERROR */
2711
+ zstream_run(&gz->z, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str),
2712
+ Z_SYNC_FLUSH);
2713
+ RB_GC_GUARD(str);
2714
+ }
2715
+ if (ZSTREAM_BUF_FILLED(&gz->z) > 0) break;
2716
+ }
2717
+ return ZSTREAM_BUF_FILLED(&gz->z);
2718
+ }
2719
+
2720
+ static void
2721
+ gzfile_calc_crc(struct gzfile *gz, VALUE str)
2722
+ {
2723
+ if (RSTRING_LEN(str) <= gz->ungetc) {
2724
+ gz->ungetc -= RSTRING_LEN(str);
2725
+ }
2726
+ else {
2727
+ gz->crc = checksum_long(crc32, gz->crc, (Bytef*)RSTRING_PTR(str) + gz->ungetc,
2728
+ RSTRING_LEN(str) - gz->ungetc);
2729
+ gz->ungetc = 0;
2730
+ }
2731
+ }
2732
+
2733
+ static VALUE
2734
+ gzfile_newstr(struct gzfile *gz, VALUE str)
2735
+ {
2736
+ if (!gz->enc2) {
2737
+ rb_enc_associate(str, gz->enc);
2738
+ return str;
2739
+ }
2740
+ if (gz->ec && rb_enc_dummy_p(gz->enc2)) {
2741
+ str = rb_econv_str_convert(gz->ec, str, ECONV_PARTIAL_INPUT);
2742
+ rb_enc_associate(str, gz->enc);
2743
+ return str;
2744
+ }
2745
+ return rb_str_conv_enc_opts(str, gz->enc2, gz->enc,
2746
+ gz->ecflags, gz->ecopts);
2747
+ }
2748
+
2749
+ static long
2750
+ gzfile_fill(struct gzfile *gz, long len)
2751
+ {
2752
+ if (len < 0)
2753
+ rb_raise(rb_eArgError, "negative length %ld given", len);
2754
+ if (len == 0)
2755
+ return 0;
2756
+ while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) < len) {
2757
+ gzfile_read_more(gz, Qnil);
2758
+ }
2759
+ if (GZFILE_IS_FINISHED(gz)) {
2760
+ if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2761
+ gzfile_check_footer(gz, Qnil);
2762
+ }
2763
+ return -1;
2764
+ }
2765
+ return len < ZSTREAM_BUF_FILLED(&gz->z) ? len : ZSTREAM_BUF_FILLED(&gz->z);
2766
+ }
2767
+
2768
+ static VALUE
2769
+ gzfile_read(struct gzfile *gz, long len)
2770
+ {
2771
+ VALUE dst;
2772
+
2773
+ len = gzfile_fill(gz, len);
2774
+ if (len == 0) return rb_str_new(0, 0);
2775
+ if (len < 0) return Qnil;
2776
+ dst = zstream_shift_buffer(&gz->z, len);
2777
+ if (!NIL_P(dst)) gzfile_calc_crc(gz, dst);
2778
+ return dst;
2779
+ }
2780
+
2781
+ static VALUE
2782
+ gzfile_readpartial(struct gzfile *gz, long len, VALUE outbuf)
2783
+ {
2784
+ VALUE dst;
2785
+
2786
+ if (len < 0)
2787
+ rb_raise(rb_eArgError, "negative length %ld given", len);
2788
+
2789
+ if (len == 0) {
2790
+ if (NIL_P(outbuf))
2791
+ return rb_str_new(0, 0);
2792
+ else {
2793
+ rb_str_resize(outbuf, 0);
2794
+ return outbuf;
2795
+ }
2796
+ }
2797
+ while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) == 0) {
2798
+ gzfile_read_more(gz, outbuf);
2799
+ }
2800
+ if (GZFILE_IS_FINISHED(gz)) {
2801
+ if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2802
+ gzfile_check_footer(gz, outbuf);
2803
+ }
2804
+ if (!NIL_P(outbuf))
2805
+ rb_str_resize(outbuf, 0);
2806
+ rb_raise(rb_eEOFError, "end of file reached");
2807
+ }
2808
+
2809
+ dst = zstream_shift_buffer(&gz->z, len);
2810
+ gzfile_calc_crc(gz, dst);
2811
+
2812
+ if (!NIL_P(outbuf)) {
2813
+ rb_str_resize(outbuf, RSTRING_LEN(dst));
2814
+ memcpy(RSTRING_PTR(outbuf), RSTRING_PTR(dst), RSTRING_LEN(dst));
2815
+ rb_str_resize(dst, 0);
2816
+ rb_gc_force_recycle(dst);
2817
+ dst = outbuf;
2818
+ }
2819
+ return dst;
2820
+ }
2821
+
2822
+ static VALUE
2823
+ gzfile_read_all(struct gzfile *gz)
2824
+ {
2825
+ VALUE dst;
2826
+
2827
+ while (!ZSTREAM_IS_FINISHED(&gz->z)) {
2828
+ gzfile_read_more(gz, Qnil);
2829
+ }
2830
+ if (GZFILE_IS_FINISHED(gz)) {
2831
+ if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2832
+ gzfile_check_footer(gz, Qnil);
2833
+ }
2834
+ return rb_str_new(0, 0);
2835
+ }
2836
+
2837
+ dst = zstream_detach_buffer(&gz->z);
2838
+ if (NIL_P(dst)) return dst;
2839
+ gzfile_calc_crc(gz, dst);
2840
+ return gzfile_newstr(gz, dst);
2841
+ }
2842
+
2843
+ static VALUE
2844
+ gzfile_getc(struct gzfile *gz)
2845
+ {
2846
+ VALUE buf, dst = 0;
2847
+ int len;
2848
+
2849
+ len = rb_enc_mbmaxlen(gz->enc);
2850
+ while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) < len) {
2851
+ gzfile_read_more(gz, Qnil);
2852
+ }
2853
+ if (GZFILE_IS_FINISHED(gz)) {
2854
+ if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2855
+ gzfile_check_footer(gz, Qnil);
2856
+ }
2857
+ return Qnil;
2858
+ }
2859
+
2860
+ if (gz->ec && rb_enc_dummy_p(gz->enc2)) {
2861
+ const unsigned char *ss, *sp, *se;
2862
+ unsigned char *ds, *dp, *de;
2863
+ VALUE cbuf = rb_enc_str_new(0, GZFILE_CBUF_CAPA, gz->enc);
2864
+
2865
+ ss = sp = (const unsigned char*)RSTRING_PTR(gz->z.buf);
2866
+ se = sp + ZSTREAM_BUF_FILLED(&gz->z);
2867
+ ds = dp = (unsigned char *)RSTRING_PTR(cbuf);
2868
+ de = (unsigned char *)ds + GZFILE_CBUF_CAPA;
2869
+ (void)rb_econv_convert(gz->ec, &sp, se, &dp, de, ECONV_PARTIAL_INPUT|ECONV_AFTER_OUTPUT);
2870
+ rb_econv_check_error(gz->ec);
2871
+ dst = zstream_shift_buffer(&gz->z, sp - ss);
2872
+ gzfile_calc_crc(gz, dst);
2873
+ rb_str_resize(cbuf, dp - ds);
2874
+ return cbuf;
2875
+ }
2876
+ else {
2877
+ buf = gz->z.buf;
2878
+ len = rb_enc_mbclen(RSTRING_PTR(buf), RSTRING_END(buf), gz->enc);
2879
+ dst = gzfile_read(gz, len);
2880
+ if (NIL_P(dst)) return dst;
2881
+ return gzfile_newstr(gz, dst);
2882
+ }
2883
+ }
2884
+
2885
+ static void
2886
+ gzfile_ungets(struct gzfile *gz, const Bytef *b, long len)
2887
+ {
2888
+ zstream_buffer_ungets(&gz->z, b, len);
2889
+ gz->ungetc+=len;
2890
+ }
2891
+
2892
+ static void
2893
+ gzfile_ungetbyte(struct gzfile *gz, int c)
2894
+ {
2895
+ zstream_buffer_ungetbyte(&gz->z, c);
2896
+ gz->ungetc++;
2897
+ }
2898
+
2899
+ static VALUE
2900
+ gzfile_writer_end_run(VALUE arg)
2901
+ {
2902
+ struct gzfile *gz = (struct gzfile *)arg;
2903
+
2904
+ if (!(gz->z.flags & GZFILE_FLAG_HEADER_FINISHED)) {
2905
+ gzfile_make_header(gz);
2906
+ }
2907
+
2908
+ zstream_run(&gz->z, (Bytef*)"", 0, Z_FINISH);
2909
+ gzfile_make_footer(gz);
2910
+ gzfile_write_raw(gz);
2911
+
2912
+ return Qnil;
2913
+ }
2914
+
2915
+ static void
2916
+ gzfile_writer_end(struct gzfile *gz)
2917
+ {
2918
+ if (ZSTREAM_IS_CLOSING(&gz->z)) return;
2919
+ gz->z.flags |= ZSTREAM_FLAG_CLOSING;
2920
+
2921
+ rb_ensure(gzfile_writer_end_run, (VALUE)gz, zstream_ensure_end, (VALUE)&gz->z);
2922
+ }
2923
+
2924
+ static VALUE
2925
+ gzfile_reader_end_run(VALUE arg)
2926
+ {
2927
+ struct gzfile *gz = (struct gzfile *)arg;
2928
+
2929
+ if (GZFILE_IS_FINISHED(gz)
2930
+ && !(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2931
+ gzfile_check_footer(gz, Qnil);
2932
+ }
2933
+
2934
+ return Qnil;
2935
+ }
2936
+
2937
+ static void
2938
+ gzfile_reader_end(struct gzfile *gz)
2939
+ {
2940
+ if (ZSTREAM_IS_CLOSING(&gz->z)) return;
2941
+ gz->z.flags |= ZSTREAM_FLAG_CLOSING;
2942
+
2943
+ rb_ensure(gzfile_reader_end_run, (VALUE)gz, zstream_ensure_end, (VALUE)&gz->z);
2944
+ }
2945
+
2946
+ static void
2947
+ gzfile_reader_rewind(struct gzfile *gz)
2948
+ {
2949
+ long n;
2950
+
2951
+ n = gz->z.stream.total_in;
2952
+ if (!NIL_P(gz->z.input)) {
2953
+ n += RSTRING_LEN(gz->z.input);
2954
+ }
2955
+
2956
+ rb_funcall(gz->io, id_seek, 2, rb_int2inum(-n), INT2FIX(1));
2957
+ gzfile_reset(gz);
2958
+ }
2959
+
2960
+ static VALUE
2961
+ gzfile_reader_get_unused(struct gzfile *gz)
2962
+ {
2963
+ VALUE str;
2964
+
2965
+ if (!ZSTREAM_IS_READY(&gz->z)) return Qnil;
2966
+ if (!GZFILE_IS_FINISHED(gz)) return Qnil;
2967
+ if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2968
+ gzfile_check_footer(gz, Qnil);
2969
+ }
2970
+ if (NIL_P(gz->z.input)) return Qnil;
2971
+
2972
+ str = rb_str_resurrect(gz->z.input);
2973
+ return str;
2974
+ }
2975
+
2976
+ static struct gzfile *
2977
+ get_gzfile(VALUE obj)
2978
+ {
2979
+ struct gzfile *gz;
2980
+
2981
+ TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
2982
+ if (!ZSTREAM_IS_READY(&gz->z)) {
2983
+ rb_raise(cGzError, "closed gzip stream");
2984
+ }
2985
+ return gz;
2986
+ }
2987
+
2988
+
2989
+ /* ------------------------------------------------------------------------- */
2990
+
2991
+ /*
2992
+ * Document-class: Zstdlib::GzipFile
2993
+ *
2994
+ * Zstdlib::GzipFile is an abstract class for handling a gzip formatted
2995
+ * compressed file. The operations are defined in the subclasses,
2996
+ * Zstdlib::GzipReader for reading, and Zstdlib::GzipWriter for writing.
2997
+ *
2998
+ * GzipReader should be used by associating an IO, or IO-like, object.
2999
+ *
3000
+ * == Method Catalogue
3001
+ *
3002
+ * - ::wrap
3003
+ * - ::open (Zstdlib::GzipReader::open and Zstdlib::GzipWriter::open)
3004
+ * - #close
3005
+ * - #closed?
3006
+ * - #comment
3007
+ * - comment= (Zstdlib::GzipWriter#comment=)
3008
+ * - #crc
3009
+ * - eof? (Zstdlib::GzipReader#eof?)
3010
+ * - #finish
3011
+ * - #level
3012
+ * - lineno (Zstdlib::GzipReader#lineno)
3013
+ * - lineno= (Zstdlib::GzipReader#lineno=)
3014
+ * - #mtime
3015
+ * - mtime= (Zstdlib::GzipWriter#mtime=)
3016
+ * - #orig_name
3017
+ * - orig_name (Zstdlib::GzipWriter#orig_name=)
3018
+ * - #os_code
3019
+ * - path (when the underlying IO supports #path)
3020
+ * - #sync
3021
+ * - #sync=
3022
+ * - #to_io
3023
+ *
3024
+ * (due to internal structure, documentation may appear under Zstdlib::GzipReader
3025
+ * or Zstdlib::GzipWriter)
3026
+ */
3027
+
3028
+
3029
+ typedef struct {
3030
+ int argc;
3031
+ VALUE *argv;
3032
+ VALUE klass;
3033
+ } new_wrap_arg_t;
3034
+
3035
+ static VALUE
3036
+ new_wrap(VALUE tmp)
3037
+ {
3038
+ new_wrap_arg_t *arg = (new_wrap_arg_t *)tmp;
3039
+ return rb_class_new_instance_kw(arg->argc, arg->argv, arg->klass, RB_PASS_CALLED_KEYWORDS);
3040
+ }
3041
+
3042
+ static VALUE
3043
+ gzfile_ensure_close(VALUE obj)
3044
+ {
3045
+ struct gzfile *gz;
3046
+
3047
+ TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
3048
+ if (ZSTREAM_IS_READY(&gz->z)) {
3049
+ gzfile_close(gz, 1);
3050
+ }
3051
+ return Qnil;
3052
+ }
3053
+
3054
+ static VALUE
3055
+ gzfile_wrap(int argc, VALUE *argv, VALUE klass, int close_io_on_error)
3056
+ {
3057
+ VALUE obj;
3058
+
3059
+ if (close_io_on_error) {
3060
+ int state = 0;
3061
+ new_wrap_arg_t arg;
3062
+ arg.argc = argc;
3063
+ arg.argv = argv;
3064
+ arg.klass = klass;
3065
+ obj = rb_protect(new_wrap, (VALUE)&arg, &state);
3066
+ if (state) {
3067
+ rb_io_close(argv[0]);
3068
+ rb_jump_tag(state);
3069
+ }
3070
+ }
3071
+ else {
3072
+ obj = rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
3073
+ }
3074
+
3075
+ if (rb_block_given_p()) {
3076
+ return rb_ensure(rb_yield, obj, gzfile_ensure_close, obj);
3077
+ }
3078
+ else {
3079
+ return obj;
3080
+ }
3081
+ }
3082
+
3083
+ /*
3084
+ * Document-method: Zstdlib::GzipFile.wrap
3085
+ *
3086
+ * call-seq:
3087
+ * Zstdlib::GzipReader.wrap(io, ...) { |gz| ... }
3088
+ * Zstdlib::GzipWriter.wrap(io, ...) { |gz| ... }
3089
+ *
3090
+ * Creates a GzipReader or GzipWriter associated with +io+, passing in any
3091
+ * necessary extra options, and executes the block with the newly created
3092
+ * object just like File.open.
3093
+ *
3094
+ * The GzipFile object will be closed automatically after executing the block.
3095
+ * If you want to keep the associated IO object open, you may call
3096
+ * Zstdlib::GzipFile#finish method in the block.
3097
+ */
3098
+ static VALUE
3099
+ rb_gzfile_s_wrap(int argc, VALUE *argv, VALUE klass)
3100
+ {
3101
+ return gzfile_wrap(argc, argv, klass, 0);
3102
+ }
3103
+
3104
+ /*
3105
+ * Document-method: Zstdlib::GzipFile.open
3106
+ *
3107
+ * See Zstdlib::GzipReader#open and Zstdlib::GzipWriter#open.
3108
+ */
3109
+ static VALUE
3110
+ gzfile_s_open(int argc, VALUE *argv, VALUE klass, const char *mode)
3111
+ {
3112
+ VALUE io, filename;
3113
+
3114
+ rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
3115
+ filename = argv[0];
3116
+ io = rb_file_open_str(filename, mode);
3117
+ argv[0] = io;
3118
+ return gzfile_wrap(argc, argv, klass, 1);
3119
+ }
3120
+
3121
+ /*
3122
+ * Document-method: Zstdlib::GzipFile#to_io
3123
+ *
3124
+ * Same as IO.
3125
+ */
3126
+ static VALUE
3127
+ rb_gzfile_to_io(VALUE obj)
3128
+ {
3129
+ return get_gzfile(obj)->io;
3130
+ }
3131
+
3132
+ /*
3133
+ * Document-method: Zstdlib::GzipFile#crc
3134
+ *
3135
+ * Returns CRC value of the uncompressed data.
3136
+ */
3137
+ static VALUE
3138
+ rb_gzfile_crc(VALUE obj)
3139
+ {
3140
+ return rb_uint2inum(get_gzfile(obj)->crc);
3141
+ }
3142
+
3143
+ /*
3144
+ * Document-method: Zstdlib::GzipFile#mtime
3145
+ *
3146
+ * Returns last modification time recorded in the gzip file header.
3147
+ */
3148
+ static VALUE
3149
+ rb_gzfile_mtime(VALUE obj)
3150
+ {
3151
+ return rb_time_new(get_gzfile(obj)->mtime, (time_t)0);
3152
+ }
3153
+
3154
+ /*
3155
+ * Document-method: Zstdlib::GzipFile#level
3156
+ *
3157
+ * Returns compression level.
3158
+ */
3159
+ static VALUE
3160
+ rb_gzfile_level(VALUE obj)
3161
+ {
3162
+ return INT2FIX(get_gzfile(obj)->level);
3163
+ }
3164
+
3165
+ /*
3166
+ * Document-method: Zstdlib::GzipFile#os_code
3167
+ *
3168
+ * Returns OS code number recorded in the gzip file header.
3169
+ */
3170
+ static VALUE
3171
+ rb_gzfile_os_code(VALUE obj)
3172
+ {
3173
+ return INT2FIX(get_gzfile(obj)->os_code);
3174
+ }
3175
+
3176
+ /*
3177
+ * Document-method: Zstdlib::GzipFile#orig_name
3178
+ *
3179
+ * Returns original filename recorded in the gzip file header, or +nil+ if
3180
+ * original filename is not present.
3181
+ */
3182
+ static VALUE
3183
+ rb_gzfile_orig_name(VALUE obj)
3184
+ {
3185
+ VALUE str = get_gzfile(obj)->orig_name;
3186
+ if (!NIL_P(str)) {
3187
+ str = rb_str_dup(str);
3188
+ }
3189
+ return str;
3190
+ }
3191
+
3192
+ /*
3193
+ * Document-method: Zstdlib::GzipFile#comment
3194
+ *
3195
+ * Returns comments recorded in the gzip file header, or nil if the comments
3196
+ * is not present.
3197
+ */
3198
+ static VALUE
3199
+ rb_gzfile_comment(VALUE obj)
3200
+ {
3201
+ VALUE str = get_gzfile(obj)->comment;
3202
+ if (!NIL_P(str)) {
3203
+ str = rb_str_dup(str);
3204
+ }
3205
+ return str;
3206
+ }
3207
+
3208
+ /*
3209
+ * Document-method: Zstdlib::GzipFile#lineno
3210
+ *
3211
+ * The line number of the last row read from this file.
3212
+ */
3213
+ static VALUE
3214
+ rb_gzfile_lineno(VALUE obj)
3215
+ {
3216
+ return INT2NUM(get_gzfile(obj)->lineno);
3217
+ }
3218
+
3219
+ /*
3220
+ * Document-method: Zstdlib::GzipReader#lineno=
3221
+ *
3222
+ * Specify line number of the last row read from this file.
3223
+ */
3224
+ static VALUE
3225
+ rb_gzfile_set_lineno(VALUE obj, VALUE lineno)
3226
+ {
3227
+ struct gzfile *gz = get_gzfile(obj);
3228
+ gz->lineno = NUM2INT(lineno);
3229
+ return lineno;
3230
+ }
3231
+
3232
+ /*
3233
+ * Document-method: Zstdlib::GzipWriter#mtime=
3234
+ *
3235
+ * Specify the modification time (+mtime+) in the gzip header.
3236
+ * Using an Integer.
3237
+ *
3238
+ * Setting the mtime in the gzip header does not effect the
3239
+ * mtime of the file generated. Different utilities that
3240
+ * expand the gzipped files may use the mtime
3241
+ * header. For example the gunzip utility can use the `-N`
3242
+ * flag which will set the resultant file's mtime to the
3243
+ * value in the header. By default many tools will set
3244
+ * the mtime of the expanded file to the mtime of the
3245
+ * gzipped file, not the mtime in the header.
3246
+ *
3247
+ * If you do not set an mtime, the default value will be the time
3248
+ * when compression started. Setting a value of 0 indicates
3249
+ * no time stamp is available.
3250
+ */
3251
+ static VALUE
3252
+ rb_gzfile_set_mtime(VALUE obj, VALUE mtime)
3253
+ {
3254
+ struct gzfile *gz = get_gzfile(obj);
3255
+ VALUE val;
3256
+
3257
+ if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
3258
+ rb_raise(cGzError, "header is already written");
3259
+ }
3260
+
3261
+ val = rb_Integer(mtime);
3262
+ gz->mtime = NUM2UINT(val);
3263
+ gz->z.flags |= GZFILE_FLAG_MTIME_IS_SET;
3264
+
3265
+ return mtime;
3266
+ }
3267
+
3268
+ /*
3269
+ * Document-method: Zstdlib::GzipFile#orig_name=
3270
+ *
3271
+ * Specify the original name (+str+) in the gzip header.
3272
+ */
3273
+ static VALUE
3274
+ rb_gzfile_set_orig_name(VALUE obj, VALUE str)
3275
+ {
3276
+ struct gzfile *gz = get_gzfile(obj);
3277
+ VALUE s;
3278
+ char *p;
3279
+
3280
+ if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
3281
+ rb_raise(cGzError, "header is already written");
3282
+ }
3283
+ s = rb_str_dup(rb_str_to_str(str));
3284
+ p = memchr(RSTRING_PTR(s), '\0', RSTRING_LEN(s));
3285
+ if (p) {
3286
+ rb_str_resize(s, p - RSTRING_PTR(s));
3287
+ }
3288
+ gz->orig_name = s;
3289
+ return str;
3290
+ }
3291
+
3292
+ /*
3293
+ * Document-method: Zstdlib::GzipFile#comment=
3294
+ *
3295
+ * Specify the comment (+str+) in the gzip header.
3296
+ */
3297
+ static VALUE
3298
+ rb_gzfile_set_comment(VALUE obj, VALUE str)
3299
+ {
3300
+ struct gzfile *gz = get_gzfile(obj);
3301
+ VALUE s;
3302
+ char *p;
3303
+
3304
+ if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
3305
+ rb_raise(cGzError, "header is already written");
3306
+ }
3307
+ s = rb_str_dup(rb_str_to_str(str));
3308
+ p = memchr(RSTRING_PTR(s), '\0', RSTRING_LEN(s));
3309
+ if (p) {
3310
+ rb_str_resize(s, p - RSTRING_PTR(s));
3311
+ }
3312
+ gz->comment = s;
3313
+ return str;
3314
+ }
3315
+
3316
+ /*
3317
+ * Document-method: Zstdlib::GzipFile#close
3318
+ *
3319
+ * Closes the GzipFile object. This method calls close method of the
3320
+ * associated IO object. Returns the associated IO object.
3321
+ */
3322
+ static VALUE
3323
+ rb_gzfile_close(VALUE obj)
3324
+ {
3325
+ struct gzfile *gz;
3326
+ VALUE io;
3327
+
3328
+ TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
3329
+ if (!ZSTREAM_IS_READY(&gz->z)) {
3330
+ return Qnil;
3331
+ }
3332
+ io = gz->io;
3333
+ gzfile_close(gz, 1);
3334
+ return io;
3335
+ }
3336
+
3337
+ /*
3338
+ * Document-method: Zstdlib::GzipFile#finish
3339
+ *
3340
+ * Closes the GzipFile object. Unlike Zstdlib::GzipFile#close, this method never
3341
+ * calls the close method of the associated IO object. Returns the associated IO
3342
+ * object.
3343
+ */
3344
+ static VALUE
3345
+ rb_gzfile_finish(VALUE obj)
3346
+ {
3347
+ struct gzfile *gz = get_gzfile(obj);
3348
+ VALUE io;
3349
+
3350
+ io = gz->io;
3351
+ gzfile_close(gz, 0);
3352
+ return io;
3353
+ }
3354
+
3355
+ /*
3356
+ * Document-method: Zstdlib::GzipFile#closed?
3357
+ *
3358
+ * Same as IO#closed?
3359
+ *
3360
+ */
3361
+ static VALUE
3362
+ rb_gzfile_closed_p(VALUE obj)
3363
+ {
3364
+ struct gzfile *gz;
3365
+ TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
3366
+ return NIL_P(gz->io) ? Qtrue : Qfalse;
3367
+ }
3368
+
3369
+ /*
3370
+ * Document-method: Zstdlib::GzipFile#eof?
3371
+ *
3372
+ * Returns +true+ or +false+ whether the stream has reached the end.
3373
+ */
3374
+ static VALUE
3375
+ rb_gzfile_eof_p(VALUE obj)
3376
+ {
3377
+ struct gzfile *gz = get_gzfile(obj);
3378
+ return GZFILE_IS_FINISHED(gz) ? Qtrue : Qfalse;
3379
+ }
3380
+
3381
+ /*
3382
+ * Document-method: Zstdlib::GzipFile#sync
3383
+ *
3384
+ * Same as IO#sync
3385
+ *
3386
+ */
3387
+ static VALUE
3388
+ rb_gzfile_sync(VALUE obj)
3389
+ {
3390
+ return (get_gzfile(obj)->z.flags & GZFILE_FLAG_SYNC) ? Qtrue : Qfalse;
3391
+ }
3392
+
3393
+ /*
3394
+ * Document-method: Zstdlib::GzipFile#sync=
3395
+ *
3396
+ * call-seq: sync = flag
3397
+ *
3398
+ * Same as IO. If flag is +true+, the associated IO object must respond to the
3399
+ * +flush+ method. While +sync+ mode is +true+, the compression ratio
3400
+ * decreases sharply.
3401
+ */
3402
+ static VALUE
3403
+ rb_gzfile_set_sync(VALUE obj, VALUE mode)
3404
+ {
3405
+ struct gzfile *gz = get_gzfile(obj);
3406
+
3407
+ if (RTEST(mode)) {
3408
+ gz->z.flags |= GZFILE_FLAG_SYNC;
3409
+ }
3410
+ else {
3411
+ gz->z.flags &= ~GZFILE_FLAG_SYNC;
3412
+ }
3413
+ return mode;
3414
+ }
3415
+
3416
+ /*
3417
+ * Document-method: Zstdlib::GzipFile#total_in
3418
+ *
3419
+ * Total number of input bytes read so far.
3420
+ */
3421
+ static VALUE
3422
+ rb_gzfile_total_in(VALUE obj)
3423
+ {
3424
+ return rb_uint2inum(get_gzfile(obj)->z.stream.total_in);
3425
+ }
3426
+
3427
+ /*
3428
+ * Document-method: Zstdlib::GzipFile#total_out
3429
+ *
3430
+ * Total number of output bytes output so far.
3431
+ */
3432
+ static VALUE
3433
+ rb_gzfile_total_out(VALUE obj)
3434
+ {
3435
+ struct gzfile *gz = get_gzfile(obj);
3436
+ uLong total_out = gz->z.stream.total_out;
3437
+ long buf_filled = ZSTREAM_BUF_FILLED(&gz->z);
3438
+
3439
+ if (total_out >= (uLong)buf_filled) {
3440
+ return rb_uint2inum(total_out - buf_filled);
3441
+ } else {
3442
+ return LONG2FIX(-(buf_filled - (long)total_out));
3443
+ }
3444
+ }
3445
+
3446
+ /*
3447
+ * Document-method: Zstdlib::GzipFile#path
3448
+ *
3449
+ * call-seq: path
3450
+ *
3451
+ * Returns the path string of the associated IO-like object. This
3452
+ * method is only defined when the IO-like object responds to #path().
3453
+ */
3454
+ static VALUE
3455
+ rb_gzfile_path(VALUE obj)
3456
+ {
3457
+ struct gzfile *gz;
3458
+ TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
3459
+ return gz->path;
3460
+ }
3461
+
3462
+ static void
3463
+ rb_gzfile_ecopts(struct gzfile *gz, VALUE opts)
3464
+ {
3465
+ if (!NIL_P(opts)) {
3466
+ rb_io_extract_encoding_option(opts, &gz->enc, &gz->enc2, NULL);
3467
+ }
3468
+ if (gz->enc2) {
3469
+ gz->ecflags = rb_econv_prepare_opts(opts, &opts);
3470
+ gz->ec = rb_econv_open_opts(gz->enc2->name, gz->enc->name,
3471
+ gz->ecflags, opts);
3472
+ gz->ecopts = opts;
3473
+ }
3474
+ }
3475
+
3476
+ /* ------------------------------------------------------------------------- */
3477
+
3478
+ /*
3479
+ * Document-class: Zstdlib::GzipWriter
3480
+ *
3481
+ * Zstdlib::GzipWriter is a class for writing gzipped files. GzipWriter should
3482
+ * be used with an instance of IO, or IO-like, object.
3483
+ *
3484
+ * Following two example generate the same result.
3485
+ *
3486
+ * Zstdlib::GzipWriter.open('hoge.gz') do |gz|
3487
+ * gz.write 'jugemu jugemu gokou no surikire...'
3488
+ * end
3489
+ *
3490
+ * File.open('hoge.gz', 'w') do |f|
3491
+ * gz = Zstdlib::GzipWriter.new(f)
3492
+ * gz.write 'jugemu jugemu gokou no surikire...'
3493
+ * gz.close
3494
+ * end
3495
+ *
3496
+ * To make like gzip(1) does, run following:
3497
+ *
3498
+ * orig = 'hoge.txt'
3499
+ * Zstdlib::GzipWriter.open('hoge.gz') do |gz|
3500
+ * gz.mtime = File.mtime(orig)
3501
+ * gz.orig_name = orig
3502
+ * gz.write IO.binread(orig)
3503
+ * end
3504
+ *
3505
+ * NOTE: Due to the limitation of Ruby's finalizer, you must explicitly close
3506
+ * GzipWriter objects by Zstdlib::GzipWriter#close etc. Otherwise, GzipWriter
3507
+ * will be not able to write the gzip footer and will generate a broken gzip
3508
+ * file.
3509
+ */
3510
+
3511
+ static VALUE
3512
+ rb_gzwriter_s_allocate(VALUE klass)
3513
+ {
3514
+ return gzfile_writer_new(klass);
3515
+ }
3516
+
3517
+ /*
3518
+ * call-seq: Zstdlib::GzipWriter.open(filename, level=nil, strategy=nil) { |gz| ... }
3519
+ *
3520
+ * Opens a file specified by +filename+ for writing gzip compressed data, and
3521
+ * returns a GzipWriter object associated with that file. Further details of
3522
+ * this method are found in Zstdlib::GzipWriter.new and Zstdlib::GzipFile.wrap.
3523
+ */
3524
+ static VALUE
3525
+ rb_gzwriter_s_open(int argc, VALUE *argv, VALUE klass)
3526
+ {
3527
+ return gzfile_s_open(argc, argv, klass, "wb");
3528
+ }
3529
+
3530
+ /*
3531
+ * call-seq:
3532
+ * Zstdlib::GzipWriter.new(io, level = nil, strategy = nil, options = {})
3533
+ *
3534
+ * Creates a GzipWriter object associated with +io+. +level+ and +strategy+
3535
+ * should be the same as the arguments of Zstdlib::Deflate.new. The GzipWriter
3536
+ * object writes gzipped data to +io+. +io+ must respond to the
3537
+ * +write+ method that behaves the same as IO#write.
3538
+ *
3539
+ * The +options+ hash may be used to set the encoding of the data.
3540
+ * +:external_encoding+, +:internal_encoding+ and +:encoding+ may be set as in
3541
+ * IO::new.
3542
+ */
3543
+ static VALUE
3544
+ rb_gzwriter_initialize(int argc, VALUE *argv, VALUE obj)
3545
+ {
3546
+ struct gzfile *gz;
3547
+ VALUE io, level, strategy, opt = Qnil;
3548
+ int err;
3549
+
3550
+ if (argc > 1) {
3551
+ opt = rb_check_convert_type(argv[argc-1], T_HASH, "Hash", "to_hash");
3552
+ if (!NIL_P(opt)) argc--;
3553
+ }
3554
+
3555
+ rb_scan_args(argc, argv, "12", &io, &level, &strategy);
3556
+ TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
3557
+
3558
+ /* this is undocumented feature of zlib */
3559
+ gz->level = ARG_LEVEL(level);
3560
+ err = deflateInit2(&gz->z.stream, gz->level, Z_DEFLATED,
3561
+ -MAX_WBITS, DEF_MEM_LEVEL, ARG_STRATEGY(strategy));
3562
+ if (err != Z_OK) {
3563
+ raise_zlib_error(err, gz->z.stream.msg);
3564
+ }
3565
+ gz->io = io;
3566
+ ZSTREAM_READY(&gz->z);
3567
+ rb_gzfile_ecopts(gz, opt);
3568
+
3569
+ if (rb_respond_to(io, id_path)) {
3570
+ gz->path = rb_funcall(gz->io, id_path, 0);
3571
+ rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
3572
+ }
3573
+
3574
+ return obj;
3575
+ }
3576
+
3577
+ /*
3578
+ * call-seq: flush(flush=nil)
3579
+ *
3580
+ * Flushes all the internal buffers of the GzipWriter object. The meaning of
3581
+ * +flush+ is same as in Zstdlib::Deflate#deflate. <tt>Zstdlib::SYNC_FLUSH</tt> is used if
3582
+ * +flush+ is omitted. It is no use giving flush <tt>Zstdlib::NO_FLUSH</tt>.
3583
+ */
3584
+ static VALUE
3585
+ rb_gzwriter_flush(int argc, VALUE *argv, VALUE obj)
3586
+ {
3587
+ struct gzfile *gz = get_gzfile(obj);
3588
+ VALUE v_flush;
3589
+ int flush;
3590
+
3591
+ rb_scan_args(argc, argv, "01", &v_flush);
3592
+
3593
+ flush = FIXNUMARG(v_flush, Z_SYNC_FLUSH);
3594
+ if (flush != Z_NO_FLUSH) { /* prevent Z_BUF_ERROR */
3595
+ zstream_run(&gz->z, (Bytef*)"", 0, flush);
3596
+ }
3597
+
3598
+ gzfile_write_raw(gz);
3599
+ if (rb_respond_to(gz->io, id_flush)) {
3600
+ rb_funcall(gz->io, id_flush, 0);
3601
+ }
3602
+ return obj;
3603
+ }
3604
+
3605
+ /*
3606
+ * Same as IO.
3607
+ */
3608
+ static VALUE
3609
+ rb_gzwriter_write(int argc, VALUE *argv, VALUE obj)
3610
+ {
3611
+ struct gzfile *gz = get_gzfile(obj);
3612
+ size_t total = 0;
3613
+
3614
+ while (argc-- > 0) {
3615
+ VALUE str = *argv++;
3616
+ if (!RB_TYPE_P(str, T_STRING))
3617
+ str = rb_obj_as_string(str);
3618
+ if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
3619
+ str = rb_str_conv_enc(str, rb_enc_get(str), gz->enc2);
3620
+ }
3621
+ gzfile_write(gz, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
3622
+ total += RSTRING_LEN(str);
3623
+ RB_GC_GUARD(str);
3624
+ }
3625
+ return SIZET2NUM(total);
3626
+ }
3627
+
3628
+ /*
3629
+ * Same as IO.
3630
+ */
3631
+ static VALUE
3632
+ rb_gzwriter_putc(VALUE obj, VALUE ch)
3633
+ {
3634
+ struct gzfile *gz = get_gzfile(obj);
3635
+ char c = NUM2CHR(ch);
3636
+
3637
+ gzfile_write(gz, (Bytef*)&c, 1);
3638
+ return ch;
3639
+ }
3640
+
3641
+
3642
+
3643
+ /*
3644
+ * Document-method: <<
3645
+ * Same as IO.
3646
+ */
3647
+ #define rb_gzwriter_addstr rb_io_addstr
3648
+ /*
3649
+ * Document-method: printf
3650
+ * Same as IO.
3651
+ */
3652
+ #define rb_gzwriter_printf rb_io_printf
3653
+ /*
3654
+ * Document-method: print
3655
+ * Same as IO.
3656
+ */
3657
+ #define rb_gzwriter_print rb_io_print
3658
+ /*
3659
+ * Document-method: puts
3660
+ * Same as IO.
3661
+ */
3662
+ #define rb_gzwriter_puts rb_io_puts
3663
+
3664
+
3665
+ /* ------------------------------------------------------------------------- */
3666
+
3667
+ /*
3668
+ * Document-class: Zstdlib::GzipReader
3669
+ *
3670
+ * Zstdlib::GzipReader is the class for reading a gzipped file. GzipReader should
3671
+ * be used as an IO, or -IO-like, object.
3672
+ *
3673
+ * Zstdlib::GzipReader.open('hoge.gz') {|gz|
3674
+ * print gz.read
3675
+ * }
3676
+ *
3677
+ * File.open('hoge.gz') do |f|
3678
+ * gz = Zstdlib::GzipReader.new(f)
3679
+ * print gz.read
3680
+ * gz.close
3681
+ * end
3682
+ *
3683
+ * == Method Catalogue
3684
+ *
3685
+ * The following methods in Zstdlib::GzipReader are just like their counterparts
3686
+ * in IO, but they raise Zstdlib::Error or Zstdlib::GzipFile::Error exception if an
3687
+ * error was found in the gzip file.
3688
+ * - #each
3689
+ * - #each_line
3690
+ * - #each_byte
3691
+ * - #gets
3692
+ * - #getc
3693
+ * - #lineno
3694
+ * - #lineno=
3695
+ * - #read
3696
+ * - #readchar
3697
+ * - #readline
3698
+ * - #readlines
3699
+ * - #ungetc
3700
+ *
3701
+ * Be careful of the footer of the gzip file. A gzip file has the checksum of
3702
+ * pre-compressed data in its footer. GzipReader checks all uncompressed data
3703
+ * against that checksum at the following cases, and if it fails, raises
3704
+ * <tt>Zstdlib::GzipFile::NoFooter</tt>, <tt>Zstdlib::GzipFile::CRCError</tt>, or
3705
+ * <tt>Zstdlib::GzipFile::LengthError</tt> exception.
3706
+ *
3707
+ * - When an reading request is received beyond the end of file (the end of
3708
+ * compressed data). That is, when Zstdlib::GzipReader#read,
3709
+ * Zstdlib::GzipReader#gets, or some other methods for reading returns nil.
3710
+ * - When Zstdlib::GzipFile#close method is called after the object reaches the
3711
+ * end of file.
3712
+ * - When Zstdlib::GzipReader#unused method is called after the object reaches
3713
+ * the end of file.
3714
+ *
3715
+ * The rest of the methods are adequately described in their own
3716
+ * documentation.
3717
+ */
3718
+
3719
+ static VALUE
3720
+ rb_gzreader_s_allocate(VALUE klass)
3721
+ {
3722
+ return gzfile_reader_new(klass);
3723
+ }
3724
+
3725
+ /*
3726
+ * Document-method: Zstdlib::GzipReader.open
3727
+ *
3728
+ * call-seq: Zstdlib::GzipReader.open(filename) {|gz| ... }
3729
+ *
3730
+ * Opens a file specified by +filename+ as a gzipped file, and returns a
3731
+ * GzipReader object associated with that file. Further details of this method
3732
+ * are in Zstdlib::GzipReader.new and ZLib::GzipFile.wrap.
3733
+ */
3734
+ static VALUE
3735
+ rb_gzreader_s_open(int argc, VALUE *argv, VALUE klass)
3736
+ {
3737
+ return gzfile_s_open(argc, argv, klass, "rb");
3738
+ }
3739
+
3740
+ /*
3741
+ * Document-method: Zstdlib::GzipReader.new
3742
+ *
3743
+ * call-seq:
3744
+ * Zstdlib::GzipReader.new(io, options = {})
3745
+ *
3746
+ * Creates a GzipReader object associated with +io+. The GzipReader object reads
3747
+ * gzipped data from +io+, and parses/decompresses it. The +io+ must
3748
+ * have a +read+ method that behaves same as the IO#read.
3749
+ *
3750
+ * The +options+ hash may be used to set the encoding of the data.
3751
+ * +:external_encoding+, +:internal_encoding+ and +:encoding+ may be set as in
3752
+ * IO::new.
3753
+ *
3754
+ * If the gzip file header is incorrect, raises an Zstdlib::GzipFile::Error
3755
+ * exception.
3756
+ */
3757
+ static VALUE
3758
+ rb_gzreader_initialize(int argc, VALUE *argv, VALUE obj)
3759
+ {
3760
+ VALUE io, opt = Qnil;
3761
+ struct gzfile *gz;
3762
+ int err;
3763
+
3764
+ TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
3765
+ rb_scan_args(argc, argv, "1:", &io, &opt);
3766
+
3767
+ /* this is undocumented feature of zlib */
3768
+ err = inflateInit2(&gz->z.stream, -MAX_WBITS);
3769
+ if (err != Z_OK) {
3770
+ raise_zlib_error(err, gz->z.stream.msg);
3771
+ }
3772
+ gz->io = io;
3773
+ ZSTREAM_READY(&gz->z);
3774
+ gzfile_read_header(gz, Qnil);
3775
+ rb_gzfile_ecopts(gz, opt);
3776
+
3777
+ if (rb_respond_to(io, id_path)) {
3778
+ gz->path = rb_funcall(gz->io, id_path, 0);
3779
+ rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
3780
+ }
3781
+
3782
+ return obj;
3783
+ }
3784
+
3785
+ /*
3786
+ * Document-method: Zstdlib::GzipReader#rewind
3787
+ *
3788
+ * Resets the position of the file pointer to the point created the GzipReader
3789
+ * object. The associated IO object needs to respond to the +seek+ method.
3790
+ */
3791
+ static VALUE
3792
+ rb_gzreader_rewind(VALUE obj)
3793
+ {
3794
+ struct gzfile *gz = get_gzfile(obj);
3795
+ gzfile_reader_rewind(gz);
3796
+ return INT2FIX(0);
3797
+ }
3798
+
3799
+ /*
3800
+ * Document-method: Zstdlib::GzipReader#unused
3801
+ *
3802
+ * Returns the rest of the data which had read for parsing gzip format, or
3803
+ * +nil+ if the whole gzip file is not parsed yet.
3804
+ */
3805
+ static VALUE
3806
+ rb_gzreader_unused(VALUE obj)
3807
+ {
3808
+ struct gzfile *gz;
3809
+ TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
3810
+ return gzfile_reader_get_unused(gz);
3811
+ }
3812
+
3813
+ /*
3814
+ * Document-method: Zstdlib::GzipReader#read
3815
+ *
3816
+ * See Zstdlib::GzipReader documentation for a description.
3817
+ */
3818
+ static VALUE
3819
+ rb_gzreader_read(int argc, VALUE *argv, VALUE obj)
3820
+ {
3821
+ struct gzfile *gz = get_gzfile(obj);
3822
+ VALUE vlen;
3823
+ long len;
3824
+
3825
+ rb_scan_args(argc, argv, "01", &vlen);
3826
+ if (NIL_P(vlen)) {
3827
+ return gzfile_read_all(gz);
3828
+ }
3829
+
3830
+ len = NUM2INT(vlen);
3831
+ if (len < 0) {
3832
+ rb_raise(rb_eArgError, "negative length %ld given", len);
3833
+ }
3834
+ return gzfile_read(gz, len);
3835
+ }
3836
+
3837
+ /*
3838
+ * Document-method: Zstdlib::GzipReader#readpartial
3839
+ *
3840
+ * call-seq:
3841
+ * gzipreader.readpartial(maxlen [, outbuf]) => string, outbuf
3842
+ *
3843
+ * Reads at most <i>maxlen</i> bytes from the gziped stream but
3844
+ * it blocks only if <em>gzipreader</em> has no data immediately available.
3845
+ * If the optional <i>outbuf</i> argument is present,
3846
+ * it must reference a String, which will receive the data.
3847
+ * It raises <code>EOFError</code> on end of file.
3848
+ */
3849
+ static VALUE
3850
+ rb_gzreader_readpartial(int argc, VALUE *argv, VALUE obj)
3851
+ {
3852
+ struct gzfile *gz = get_gzfile(obj);
3853
+ VALUE vlen, outbuf;
3854
+ long len;
3855
+
3856
+ rb_scan_args(argc, argv, "11", &vlen, &outbuf);
3857
+
3858
+ len = NUM2INT(vlen);
3859
+ if (len < 0) {
3860
+ rb_raise(rb_eArgError, "negative length %ld given", len);
3861
+ }
3862
+ if (!NIL_P(outbuf))
3863
+ Check_Type(outbuf, T_STRING);
3864
+ return gzfile_readpartial(gz, len, outbuf);
3865
+ }
3866
+
3867
+ /*
3868
+ * Document-method: Zstdlib::GzipReader#getc
3869
+ *
3870
+ * See Zstdlib::GzipReader documentation for a description.
3871
+ */
3872
+ static VALUE
3873
+ rb_gzreader_getc(VALUE obj)
3874
+ {
3875
+ struct gzfile *gz = get_gzfile(obj);
3876
+
3877
+ return gzfile_getc(gz);
3878
+ }
3879
+
3880
+ /*
3881
+ * Document-method: Zstdlib::GzipReader#readchar
3882
+ *
3883
+ * See Zstdlib::GzipReader documentation for a description.
3884
+ */
3885
+ static VALUE
3886
+ rb_gzreader_readchar(VALUE obj)
3887
+ {
3888
+ VALUE dst;
3889
+ dst = rb_gzreader_getc(obj);
3890
+ if (NIL_P(dst)) {
3891
+ rb_raise(rb_eEOFError, "end of file reached");
3892
+ }
3893
+ return dst;
3894
+ }
3895
+
3896
+ /*
3897
+ * Document-method: Zstdlib::GzipReader#getbyte
3898
+ *
3899
+ * See Zstdlib::GzipReader documentation for a description.
3900
+ */
3901
+ static VALUE
3902
+ rb_gzreader_getbyte(VALUE obj)
3903
+ {
3904
+ struct gzfile *gz = get_gzfile(obj);
3905
+ VALUE dst;
3906
+
3907
+ dst = gzfile_read(gz, 1);
3908
+ if (!NIL_P(dst)) {
3909
+ dst = INT2FIX((unsigned int)(RSTRING_PTR(dst)[0]) & 0xff);
3910
+ }
3911
+ return dst;
3912
+ }
3913
+
3914
+ /*
3915
+ * Document-method: Zstdlib::GzipReader#readbyte
3916
+ *
3917
+ * See Zstdlib::GzipReader documentation for a description.
3918
+ */
3919
+ static VALUE
3920
+ rb_gzreader_readbyte(VALUE obj)
3921
+ {
3922
+ VALUE dst;
3923
+ dst = rb_gzreader_getbyte(obj);
3924
+ if (NIL_P(dst)) {
3925
+ rb_raise(rb_eEOFError, "end of file reached");
3926
+ }
3927
+ return dst;
3928
+ }
3929
+
3930
+ /*
3931
+ * Document-method: Zstdlib::GzipReader#each_char
3932
+ *
3933
+ * See Zstdlib::GzipReader documentation for a description.
3934
+ */
3935
+ static VALUE
3936
+ rb_gzreader_each_char(VALUE obj)
3937
+ {
3938
+ VALUE c;
3939
+
3940
+ RETURN_ENUMERATOR(obj, 0, 0);
3941
+
3942
+ while (!NIL_P(c = rb_gzreader_getc(obj))) {
3943
+ rb_yield(c);
3944
+ }
3945
+ return Qnil;
3946
+ }
3947
+
3948
+ /*
3949
+ * Document-method: Zstdlib::GzipReader#each_byte
3950
+ *
3951
+ * See Zstdlib::GzipReader documentation for a description.
3952
+ */
3953
+ static VALUE
3954
+ rb_gzreader_each_byte(VALUE obj)
3955
+ {
3956
+ VALUE c;
3957
+
3958
+ RETURN_ENUMERATOR(obj, 0, 0);
3959
+
3960
+ while (!NIL_P(c = rb_gzreader_getbyte(obj))) {
3961
+ rb_yield(c);
3962
+ }
3963
+ return Qnil;
3964
+ }
3965
+
3966
+ /*
3967
+ * Document-method: Zstdlib::GzipReader#bytes
3968
+ *
3969
+ * This is a deprecated alias for <code>each_byte</code>.
3970
+ */
3971
+ static VALUE
3972
+ rb_gzreader_bytes(VALUE obj)
3973
+ {
3974
+ rb_warn("Zstdlib::GzipReader#bytes is deprecated; use #each_byte instead");
3975
+ if (!rb_block_given_p())
3976
+ return rb_enumeratorize(obj, ID2SYM(rb_intern("each_byte")), 0, 0);
3977
+ return rb_gzreader_each_byte(obj);
3978
+ }
3979
+
3980
+ /*
3981
+ * Document-method: Zstdlib::GzipReader#ungetc
3982
+ *
3983
+ * See Zstdlib::GzipReader documentation for a description.
3984
+ */
3985
+ static VALUE
3986
+ rb_gzreader_ungetc(VALUE obj, VALUE s)
3987
+ {
3988
+ struct gzfile *gz;
3989
+
3990
+ if (FIXNUM_P(s))
3991
+ return rb_gzreader_ungetbyte(obj, s);
3992
+ gz = get_gzfile(obj);
3993
+ StringValue(s);
3994
+ if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
3995
+ s = rb_str_conv_enc(s, rb_enc_get(s), gz->enc2);
3996
+ }
3997
+ gzfile_ungets(gz, (const Bytef*)RSTRING_PTR(s), RSTRING_LEN(s));
3998
+ RB_GC_GUARD(s);
3999
+ return Qnil;
4000
+ }
4001
+
4002
+ /*
4003
+ * Document-method: Zstdlib::GzipReader#ungetbyte
4004
+ *
4005
+ * See Zstdlib::GzipReader documentation for a description.
4006
+ */
4007
+ static VALUE
4008
+ rb_gzreader_ungetbyte(VALUE obj, VALUE ch)
4009
+ {
4010
+ struct gzfile *gz = get_gzfile(obj);
4011
+ gzfile_ungetbyte(gz, NUM2CHR(ch));
4012
+ return Qnil;
4013
+ }
4014
+
4015
+ static void
4016
+ gzreader_skip_linebreaks(struct gzfile *gz)
4017
+ {
4018
+ VALUE str;
4019
+ char *p;
4020
+ int n;
4021
+
4022
+ while (ZSTREAM_BUF_FILLED(&gz->z) == 0) {
4023
+ if (GZFILE_IS_FINISHED(gz)) return;
4024
+ gzfile_read_more(gz, Qnil);
4025
+ }
4026
+ n = 0;
4027
+ p = RSTRING_PTR(gz->z.buf);
4028
+
4029
+ while (n++, *(p++) == '\n') {
4030
+ if (n >= ZSTREAM_BUF_FILLED(&gz->z)) {
4031
+ str = zstream_detach_buffer(&gz->z);
4032
+ gzfile_calc_crc(gz, str);
4033
+ while (ZSTREAM_BUF_FILLED(&gz->z) == 0) {
4034
+ if (GZFILE_IS_FINISHED(gz)) return;
4035
+ gzfile_read_more(gz, Qnil);
4036
+ }
4037
+ n = 0;
4038
+ p = RSTRING_PTR(gz->z.buf);
4039
+ }
4040
+ }
4041
+
4042
+ str = zstream_shift_buffer(&gz->z, n - 1);
4043
+ gzfile_calc_crc(gz, str);
4044
+ }
4045
+
4046
+ static void
4047
+ rscheck(const char *rsptr, long rslen, VALUE rs)
4048
+ {
4049
+ if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
4050
+ rb_raise(rb_eRuntimeError, "rs modified");
4051
+ }
4052
+
4053
+ static long
4054
+ gzreader_charboundary(struct gzfile *gz, long n)
4055
+ {
4056
+ char *s = RSTRING_PTR(gz->z.buf);
4057
+ char *e = s + ZSTREAM_BUF_FILLED(&gz->z);
4058
+ char *p = rb_enc_left_char_head(s, s + n, e, gz->enc);
4059
+ long l = p - s;
4060
+ if (l < n) {
4061
+ n = rb_enc_precise_mbclen(p, e, gz->enc);
4062
+ if (MBCLEN_NEEDMORE_P(n)) {
4063
+ if ((l = gzfile_fill(gz, l + MBCLEN_NEEDMORE_LEN(n))) > 0) {
4064
+ return l;
4065
+ }
4066
+ }
4067
+ else if (MBCLEN_CHARFOUND_P(n)) {
4068
+ return l + MBCLEN_CHARFOUND_LEN(n);
4069
+ }
4070
+ }
4071
+ return n;
4072
+ }
4073
+
4074
+ static VALUE
4075
+ gzreader_gets(int argc, VALUE *argv, VALUE obj)
4076
+ {
4077
+ struct gzfile *gz = get_gzfile(obj);
4078
+ VALUE rs;
4079
+ VALUE dst;
4080
+ const char *rsptr;
4081
+ char *p, *res;
4082
+ long rslen, n, limit = -1;
4083
+ int rspara;
4084
+ rb_encoding *enc = gz->enc;
4085
+ int maxlen = rb_enc_mbmaxlen(enc);
4086
+
4087
+ if (argc == 0) {
4088
+ rs = rb_rs;
4089
+ }
4090
+ else {
4091
+ VALUE lim, tmp;
4092
+
4093
+ rb_scan_args(argc, argv, "11", &rs, &lim);
4094
+ if (!NIL_P(lim)) {
4095
+ if (!NIL_P(rs)) StringValue(rs);
4096
+ }
4097
+ else if (!NIL_P(rs)) {
4098
+ tmp = rb_check_string_type(rs);
4099
+ if (NIL_P(tmp)) {
4100
+ lim = rs;
4101
+ rs = rb_rs;
4102
+ }
4103
+ else {
4104
+ rs = tmp;
4105
+ }
4106
+ }
4107
+ if (!NIL_P(lim)) {
4108
+ limit = NUM2LONG(lim);
4109
+ if (limit == 0) return rb_str_new(0,0);
4110
+ }
4111
+ }
4112
+
4113
+ if (NIL_P(rs)) {
4114
+ if (limit < 0) {
4115
+ dst = gzfile_read_all(gz);
4116
+ if (RSTRING_LEN(dst) == 0) return Qnil;
4117
+ }
4118
+ else if ((n = gzfile_fill(gz, limit)) <= 0) {
4119
+ return Qnil;
4120
+ }
4121
+ else {
4122
+ if (maxlen > 1 && n >= limit && !GZFILE_IS_FINISHED(gz)) {
4123
+ n = gzreader_charboundary(gz, n);
4124
+ }
4125
+ else {
4126
+ n = limit;
4127
+ }
4128
+ dst = zstream_shift_buffer(&gz->z, n);
4129
+ if (NIL_P(dst)) return dst;
4130
+ gzfile_calc_crc(gz, dst);
4131
+ dst = gzfile_newstr(gz, dst);
4132
+ }
4133
+ gz->lineno++;
4134
+ return dst;
4135
+ }
4136
+
4137
+ if (RSTRING_LEN(rs) == 0) {
4138
+ rsptr = "\n\n";
4139
+ rslen = 2;
4140
+ rspara = 1;
4141
+ }
4142
+ else {
4143
+ rsptr = RSTRING_PTR(rs);
4144
+ rslen = RSTRING_LEN(rs);
4145
+ rspara = 0;
4146
+ }
4147
+
4148
+ if (rspara) {
4149
+ gzreader_skip_linebreaks(gz);
4150
+ }
4151
+
4152
+ while (ZSTREAM_BUF_FILLED(&gz->z) < rslen) {
4153
+ if (ZSTREAM_IS_FINISHED(&gz->z)) {
4154
+ if (ZSTREAM_BUF_FILLED(&gz->z) > 0) gz->lineno++;
4155
+ return gzfile_read(gz, rslen);
4156
+ }
4157
+ gzfile_read_more(gz, Qnil);
4158
+ }
4159
+
4160
+ p = RSTRING_PTR(gz->z.buf);
4161
+ n = rslen;
4162
+ for (;;) {
4163
+ long filled;
4164
+ if (n > ZSTREAM_BUF_FILLED(&gz->z)) {
4165
+ if (ZSTREAM_IS_FINISHED(&gz->z)) break;
4166
+ gzfile_read_more(gz, Qnil);
4167
+ p = RSTRING_PTR(gz->z.buf) + n - rslen;
4168
+ }
4169
+ if (!rspara) rscheck(rsptr, rslen, rs);
4170
+ filled = ZSTREAM_BUF_FILLED(&gz->z);
4171
+ if (limit > 0 && filled >= limit) {
4172
+ filled = limit;
4173
+ }
4174
+ res = memchr(p, rsptr[0], (filled - n + 1));
4175
+ if (!res) {
4176
+ n = filled;
4177
+ if (limit > 0 && filled >= limit) break;
4178
+ n++;
4179
+ }
4180
+ else {
4181
+ n += (long)(res - p);
4182
+ p = res;
4183
+ if (rslen == 1 || memcmp(p, rsptr, rslen) == 0) break;
4184
+ p++, n++;
4185
+ }
4186
+ }
4187
+ if (maxlen > 1 && n == limit && (ZSTREAM_BUF_FILLED(&gz->z) > n || !ZSTREAM_IS_FINISHED(&gz->z))) {
4188
+ n = gzreader_charboundary(gz, n);
4189
+ }
4190
+
4191
+ gz->lineno++;
4192
+ dst = gzfile_read(gz, n);
4193
+ if (NIL_P(dst)) return dst;
4194
+ if (rspara) {
4195
+ gzreader_skip_linebreaks(gz);
4196
+ }
4197
+ RB_GC_GUARD(rs);
4198
+
4199
+ return gzfile_newstr(gz, dst);
4200
+ }
4201
+
4202
+ /*
4203
+ * Document-method: Zstdlib::GzipReader#gets
4204
+ *
4205
+ * See Zstdlib::GzipReader documentation for a description.
4206
+ */
4207
+ static VALUE
4208
+ rb_gzreader_gets(int argc, VALUE *argv, VALUE obj)
4209
+ {
4210
+ VALUE dst;
4211
+ dst = gzreader_gets(argc, argv, obj);
4212
+ if (!NIL_P(dst)) {
4213
+ rb_lastline_set(dst);
4214
+ }
4215
+ return dst;
4216
+ }
4217
+
4218
+ /*
4219
+ * Document-method: Zstdlib::GzipReader#readline
4220
+ *
4221
+ * See Zstdlib::GzipReader documentation for a description.
4222
+ */
4223
+ static VALUE
4224
+ rb_gzreader_readline(int argc, VALUE *argv, VALUE obj)
4225
+ {
4226
+ VALUE dst;
4227
+ dst = rb_gzreader_gets(argc, argv, obj);
4228
+ if (NIL_P(dst)) {
4229
+ rb_raise(rb_eEOFError, "end of file reached");
4230
+ }
4231
+ return dst;
4232
+ }
4233
+
4234
+ /*
4235
+ * Document-method: Zstdlib::GzipReader#each
4236
+ *
4237
+ * See Zstdlib::GzipReader documentation for a description.
4238
+ */
4239
+ static VALUE
4240
+ rb_gzreader_each(int argc, VALUE *argv, VALUE obj)
4241
+ {
4242
+ VALUE str;
4243
+
4244
+ RETURN_ENUMERATOR(obj, 0, 0);
4245
+
4246
+ while (!NIL_P(str = gzreader_gets(argc, argv, obj))) {
4247
+ rb_yield(str);
4248
+ }
4249
+ return obj;
4250
+ }
4251
+
4252
+ /*
4253
+ * Document-method: Zstdlib::GzipReader#lines
4254
+ *
4255
+ * This is a deprecated alias for <code>each_line</code>.
4256
+ */
4257
+ static VALUE
4258
+ rb_gzreader_lines(int argc, VALUE *argv, VALUE obj)
4259
+ {
4260
+ rb_warn("Zstdlib::GzipReader#lines is deprecated; use #each_line instead");
4261
+ if (!rb_block_given_p())
4262
+ return rb_enumeratorize(obj, ID2SYM(rb_intern("each_line")), argc, argv);
4263
+ return rb_gzreader_each(argc, argv, obj);
4264
+ }
4265
+
4266
+ /*
4267
+ * Document-method: Zstdlib::GzipReader#readlines
4268
+ *
4269
+ * See Zstdlib::GzipReader documentation for a description.
4270
+ */
4271
+ static VALUE
4272
+ rb_gzreader_readlines(int argc, VALUE *argv, VALUE obj)
4273
+ {
4274
+ VALUE str, dst;
4275
+ dst = rb_ary_new();
4276
+ while (!NIL_P(str = gzreader_gets(argc, argv, obj))) {
4277
+ rb_ary_push(dst, str);
4278
+ }
4279
+ return dst;
4280
+ }
4281
+
4282
+ /*
4283
+ * Document-method: Zstdlib::GzipReader#external_encoding
4284
+ *
4285
+ * See Zstdlib::GzipReader documentation for a description.
4286
+ */
4287
+ static VALUE
4288
+ rb_gzreader_external_encoding(VALUE self)
4289
+ {
4290
+ return rb_enc_from_encoding(get_gzfile(self)->enc);
4291
+ }
4292
+
4293
+ static VALUE
4294
+ zlib_gzip_end_rescue(VALUE arg)
4295
+ {
4296
+ struct gzfile *gz = (struct gzfile *)arg;
4297
+ gz->end(gz);
4298
+ return Qnil;
4299
+ }
4300
+
4301
+ static VALUE
4302
+ zlib_gzip_ensure(VALUE arg)
4303
+ {
4304
+ return rb_rescue(zlib_gzip_end_rescue, arg, NULL, Qnil);
4305
+ }
4306
+
4307
+ static void
4308
+ zlib_gzip_end(struct gzfile *gz)
4309
+ {
4310
+ gz->z.flags |= ZSTREAM_FLAG_CLOSING;
4311
+ zstream_run(&gz->z, (Bytef*)"", 0, Z_FINISH);
4312
+ gzfile_make_footer(gz);
4313
+ zstream_end(&gz->z);
4314
+ }
4315
+
4316
+ #define OPTHASH_GIVEN_P(opts) \
4317
+ (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1))
4318
+ static ID id_level, id_strategy;
4319
+ static VALUE zlib_gzip_run(VALUE arg);
4320
+
4321
+ /*
4322
+ * call-seq:
4323
+ * Zstdlib.gzip(src, level: nil, strategy: nil) -> String
4324
+ *
4325
+ * Gzip the given +string+. Valid values of level are
4326
+ * Zstdlib::NO_COMPRESSION, Zstdlib::BEST_SPEED, Zstdlib::BEST_COMPRESSION,
4327
+ * Zstdlib::DEFAULT_COMPRESSION (default), or an integer from 0 to 9.
4328
+ *
4329
+ * This method is almost equivalent to the following code:
4330
+ *
4331
+ * def gzip(string, level: nil, strategy: nil)
4332
+ * sio = StringIO.new
4333
+ * sio.binmode
4334
+ * gz = Zstdlib::GzipWriter.new(sio, level, strategy)
4335
+ * gz.write(string)
4336
+ * gz.close
4337
+ * sio.string
4338
+ * end
4339
+ *
4340
+ * See also Zstdlib.gunzip
4341
+ *
4342
+ */
4343
+ static VALUE
4344
+ zlib_s_gzip(int argc, VALUE *argv, VALUE klass)
4345
+ {
4346
+ struct gzfile gz0;
4347
+ struct gzfile *gz = &gz0;
4348
+ int err;
4349
+ VALUE src, opts, level=Qnil, strategy=Qnil, args[2];
4350
+
4351
+ if (OPTHASH_GIVEN_P(opts)) {
4352
+ ID keyword_ids[2];
4353
+ VALUE kwargs[2];
4354
+ keyword_ids[0] = id_level;
4355
+ keyword_ids[1] = id_strategy;
4356
+ rb_get_kwargs(opts, keyword_ids, 0, 2, kwargs);
4357
+ if (kwargs[0] != Qundef) {
4358
+ level = kwargs[0];
4359
+ }
4360
+ if (kwargs[1] != Qundef) {
4361
+ strategy = kwargs[1];
4362
+ }
4363
+ }
4364
+ rb_scan_args(argc, argv, "10", &src);
4365
+ StringValue(src);
4366
+ gzfile_init(gz, &deflate_funcs, zlib_gzip_end);
4367
+ gz->level = ARG_LEVEL(level);
4368
+ err = deflateInit2(&gz->z.stream, gz->level, Z_DEFLATED,
4369
+ -MAX_WBITS, DEF_MEM_LEVEL, ARG_STRATEGY(strategy));
4370
+ if (err != Z_OK) {
4371
+ zlib_gzip_end(gz);
4372
+ raise_zlib_error(err, gz->z.stream.msg);
4373
+ }
4374
+ ZSTREAM_READY(&gz->z);
4375
+ args[0] = (VALUE)gz;
4376
+ args[1] = src;
4377
+ return rb_ensure(zlib_gzip_run, (VALUE)args, zlib_gzip_ensure, (VALUE)gz);
4378
+ }
4379
+
4380
+ static VALUE
4381
+ zlib_gzip_run(VALUE arg)
4382
+ {
4383
+ VALUE *args = (VALUE *)arg;
4384
+ struct gzfile *gz = (struct gzfile *)args[0];
4385
+ VALUE src = args[1];
4386
+ long len;
4387
+
4388
+ gzfile_make_header(gz);
4389
+ len = RSTRING_LEN(src);
4390
+ if (len > 0) {
4391
+ Bytef *ptr = (Bytef *)RSTRING_PTR(src);
4392
+ gz->crc = checksum_long(crc32, gz->crc, ptr, len);
4393
+ zstream_run(&gz->z, ptr, len, Z_NO_FLUSH);
4394
+ }
4395
+ gzfile_close(gz, 0);
4396
+ return zstream_detach_buffer(&gz->z);
4397
+ }
4398
+
4399
+ static void
4400
+ zlib_gunzip_end(struct gzfile *gz)
4401
+ {
4402
+ gz->z.flags |= ZSTREAM_FLAG_CLOSING;
4403
+ zstream_end(&gz->z);
4404
+ }
4405
+
4406
+ static VALUE zlib_gunzip_run(VALUE arg);
4407
+
4408
+ /*
4409
+ * call-seq:
4410
+ * Zstdlib.gunzip(src) -> String
4411
+ *
4412
+ * Decode the given gzipped +string+.
4413
+ *
4414
+ * This method is almost equivalent to the following code:
4415
+ *
4416
+ * def gunzip(string)
4417
+ * sio = StringIO.new(string)
4418
+ * gz = Zstdlib::GzipReader.new(sio, encoding: Encoding::ASCII_8BIT)
4419
+ * gz.read
4420
+ * ensure
4421
+ * gz&.close
4422
+ * end
4423
+ *
4424
+ * See also Zstdlib.gzip
4425
+ */
4426
+ static VALUE
4427
+ zlib_gunzip(VALUE klass, VALUE src)
4428
+ {
4429
+ struct gzfile gz0;
4430
+ struct gzfile *gz = &gz0;
4431
+ int err;
4432
+
4433
+ StringValue(src);
4434
+
4435
+ gzfile_init(gz, &inflate_funcs, zlib_gunzip_end);
4436
+ err = inflateInit2(&gz->z.stream, -MAX_WBITS);
4437
+ if (err != Z_OK) {
4438
+ raise_zlib_error(err, gz->z.stream.msg);
4439
+ }
4440
+ gz->io = Qundef;
4441
+ gz->z.input = src;
4442
+ ZSTREAM_READY(&gz->z);
4443
+ return rb_ensure(zlib_gunzip_run, (VALUE)gz, zlib_gzip_ensure, (VALUE)gz);
4444
+ }
4445
+
4446
+ static VALUE
4447
+ zlib_gunzip_run(VALUE arg)
4448
+ {
4449
+ struct gzfile *gz = (struct gzfile *)arg;
4450
+ VALUE dst;
4451
+
4452
+ gzfile_read_header(gz, Qnil);
4453
+ dst = zstream_detach_buffer(&gz->z);
4454
+ gzfile_calc_crc(gz, dst);
4455
+ if (!ZSTREAM_IS_FINISHED(&gz->z)) {
4456
+ rb_raise(cGzError, "unexpected end of file");
4457
+ }
4458
+ if (NIL_P(gz->z.input)) {
4459
+ rb_raise(cNoFooter, "footer is not found");
4460
+ }
4461
+ gzfile_check_footer(gz, Qnil);
4462
+ return dst;
4463
+ }
4464
+
4465
+ #endif /* GZIP_SUPPORT */
4466
+
4467
+ void
4468
+ Init_zstdlib(void)
4469
+ {
4470
+ #undef rb_intern
4471
+ VALUE mZlib, cZStream, cDeflate, cInflate;
4472
+ #if GZIP_SUPPORT
4473
+ VALUE cGzipFile, cGzipWriter, cGzipReader;
4474
+ #endif
4475
+
4476
+ mZlib = rb_define_module("Zstdlib");
4477
+
4478
+ id_dictionaries = rb_intern("@dictionaries");
4479
+
4480
+ cZError = rb_define_class_under(mZlib, "Error", rb_eStandardError);
4481
+ cStreamEnd = rb_define_class_under(mZlib, "StreamEnd", cZError);
4482
+ cNeedDict = rb_define_class_under(mZlib, "NeedDict", cZError);
4483
+ cDataError = rb_define_class_under(mZlib, "DataError", cZError);
4484
+ cStreamError = rb_define_class_under(mZlib, "StreamError", cZError);
4485
+ cMemError = rb_define_class_under(mZlib, "MemError", cZError);
4486
+ cBufError = rb_define_class_under(mZlib, "BufError", cZError);
4487
+ cVersionError = rb_define_class_under(mZlib, "VersionError", cZError);
4488
+
4489
+ rb_define_module_function(mZlib, "zlib_version", rb_zlib_version, 0);
4490
+ rb_define_module_function(mZlib, "adler32", rb_zlib_adler32, -1);
4491
+ rb_define_module_function(mZlib, "adler32_combine", rb_zlib_adler32_combine, 3);
4492
+ rb_define_module_function(mZlib, "crc32", rb_zlib_crc32, -1);
4493
+ rb_define_module_function(mZlib, "crc32_combine", rb_zlib_crc32_combine, 3);
4494
+ rb_define_module_function(mZlib, "crc_table", rb_zlib_crc_table, 0);
4495
+
4496
+ /* The Ruby/zlib version string. */
4497
+ rb_define_const(mZlib, "VERSION", rb_str_new2(RUBY_ZLIB_VERSION));
4498
+ /* The string which represents the version of zlib.h */
4499
+ rb_define_const(mZlib, "ZLIB_VERSION", rb_str_new2(ZLIB_VERSION));
4500
+ rb_define_const(mZlib, "ZSTD_VERSION", rb_str_new2(ZSTD_versionString()));
4501
+ rb_define_module_function(mZlib, "zstd_version", rb_zstd_version, 0);
4502
+
4503
+ cZStream = rb_define_class_under(mZlib, "ZStream", rb_cObject);
4504
+ rb_undef_alloc_func(cZStream);
4505
+ rb_define_method(cZStream, "avail_out", rb_zstream_avail_out, 0);
4506
+ rb_define_method(cZStream, "avail_out=", rb_zstream_set_avail_out, 1);
4507
+ rb_define_method(cZStream, "avail_in", rb_zstream_avail_in, 0);
4508
+ rb_define_method(cZStream, "total_in", rb_zstream_total_in, 0);
4509
+ rb_define_method(cZStream, "total_out", rb_zstream_total_out, 0);
4510
+ rb_define_method(cZStream, "data_type", rb_zstream_data_type, 0);
4511
+ rb_define_method(cZStream, "adler", rb_zstream_adler, 0);
4512
+ rb_define_method(cZStream, "finished?", rb_zstream_finished_p, 0);
4513
+ rb_define_method(cZStream, "stream_end?", rb_zstream_finished_p, 0);
4514
+ rb_define_method(cZStream, "closed?", rb_zstream_closed_p, 0);
4515
+ rb_define_method(cZStream, "ended?", rb_zstream_closed_p, 0);
4516
+ rb_define_method(cZStream, "close", rb_zstream_end, 0);
4517
+ rb_define_method(cZStream, "end", rb_zstream_end, 0);
4518
+ rb_define_method(cZStream, "reset", rb_zstream_reset, 0);
4519
+ rb_define_method(cZStream, "finish", rb_zstream_finish, 0);
4520
+ rb_define_method(cZStream, "flush_next_in", rb_zstream_flush_next_in, 0);
4521
+ rb_define_method(cZStream, "flush_next_out", rb_zstream_flush_next_out, 0);
4522
+
4523
+ /* Represents binary data as guessed by deflate.
4524
+ *
4525
+ * See Zstdlib::Deflate#data_type. */
4526
+ rb_define_const(mZlib, "BINARY", INT2FIX(Z_BINARY));
4527
+
4528
+ /* Represents text data as guessed by deflate.
4529
+ *
4530
+ * NOTE: The underlying constant Z_ASCII was deprecated in favor of Z_TEXT
4531
+ * in zlib 1.2.2. New applications should not use this constant.
4532
+ *
4533
+ * See Zstdlib::Deflate#data_type. */
4534
+ rb_define_const(mZlib, "ASCII", INT2FIX(Z_ASCII));
4535
+
4536
+ #ifdef Z_TEXT
4537
+ /* Represents text data as guessed by deflate.
4538
+ *
4539
+ * See Zstdlib::Deflate#data_type. */
4540
+ rb_define_const(mZlib, "TEXT", INT2FIX(Z_TEXT));
4541
+ #endif
4542
+
4543
+ /* Represents an unknown data type as guessed by deflate.
4544
+ *
4545
+ * See Zstdlib::Deflate#data_type. */
4546
+ rb_define_const(mZlib, "UNKNOWN", INT2FIX(Z_UNKNOWN));
4547
+
4548
+ cDeflate = rb_define_class_under(mZlib, "Deflate", cZStream);
4549
+ rb_define_singleton_method(cDeflate, "deflate", rb_deflate_s_deflate, -1);
4550
+ rb_define_singleton_method(mZlib, "deflate", rb_deflate_s_deflate, -1);
4551
+ rb_define_alloc_func(cDeflate, rb_deflate_s_allocate);
4552
+ rb_define_method(cDeflate, "initialize", rb_deflate_initialize, -1);
4553
+ rb_define_method(cDeflate, "initialize_copy", rb_deflate_init_copy, 1);
4554
+ rb_define_method(cDeflate, "deflate", rb_deflate_deflate, -1);
4555
+ rb_define_method(cDeflate, "<<", rb_deflate_addstr, 1);
4556
+ rb_define_method(cDeflate, "flush", rb_deflate_flush, -1);
4557
+ rb_define_method(cDeflate, "params", rb_deflate_params, 2);
4558
+ rb_define_method(cDeflate, "set_dictionary", rb_deflate_set_dictionary, 1);
4559
+
4560
+ cInflate = rb_define_class_under(mZlib, "Inflate", cZStream);
4561
+ rb_define_singleton_method(cInflate, "inflate", rb_inflate_s_inflate, 1);
4562
+ rb_define_singleton_method(mZlib, "inflate", rb_inflate_s_inflate, 1);
4563
+ rb_define_alloc_func(cInflate, rb_inflate_s_allocate);
4564
+ rb_define_method(cInflate, "initialize", rb_inflate_initialize, -1);
4565
+ rb_define_method(cInflate, "add_dictionary", rb_inflate_add_dictionary, 1);
4566
+ rb_define_method(cInflate, "inflate", rb_inflate_inflate, 1);
4567
+ rb_define_method(cInflate, "<<", rb_inflate_addstr, 1);
4568
+ rb_define_method(cInflate, "sync", rb_inflate_sync, 1);
4569
+ rb_define_method(cInflate, "sync_point?", rb_inflate_sync_point_p, 0);
4570
+ rb_define_method(cInflate, "set_dictionary", rb_inflate_set_dictionary, 1);
4571
+
4572
+ /* No compression, passes through data untouched. Use this for appending
4573
+ * pre-compressed data to a deflate stream.
4574
+ */
4575
+ rb_define_const(mZlib, "NO_COMPRESSION", INT2FIX(Z_NO_COMPRESSION));
4576
+ /* Fastest compression level, but with the lowest space savings. */
4577
+ rb_define_const(mZlib, "BEST_SPEED", INT2FIX(Z_BEST_SPEED));
4578
+ /* Slowest compression level, but with the best space savings. */
4579
+ rb_define_const(mZlib, "BEST_COMPRESSION", INT2FIX(ZSTD_maxCLevel()));
4580
+ /* Default compression level which is a good trade-off between space and
4581
+ * time
4582
+ */
4583
+ rb_define_const(mZlib, "DEFAULT_COMPRESSION",
4584
+ INT2FIX(ZSTD_CLEVEL_DEFAULT));
4585
+
4586
+ /* Deflate strategy for data produced by a filter (or predictor). The
4587
+ * effect of FILTERED is to force more Huffman codes and less string
4588
+ * matching; it is somewhat intermediate between DEFAULT_STRATEGY and
4589
+ * HUFFMAN_ONLY. Filtered data consists mostly of small values with a
4590
+ * somewhat random distribution.
4591
+ */
4592
+ rb_define_const(mZlib, "FILTERED", INT2FIX(Z_FILTERED));
4593
+
4594
+ /* Deflate strategy which uses Huffman codes only (no string matching). */
4595
+ rb_define_const(mZlib, "HUFFMAN_ONLY", INT2FIX(Z_HUFFMAN_ONLY));
4596
+
4597
+ #ifdef Z_RLE
4598
+ /* Deflate compression strategy designed to be almost as fast as
4599
+ * HUFFMAN_ONLY, but give better compression for PNG image data.
4600
+ */
4601
+ rb_define_const(mZlib, "RLE", INT2FIX(Z_RLE));
4602
+ #endif
4603
+
4604
+ #ifdef Z_FIXED
4605
+ /* Deflate strategy which prevents the use of dynamic Huffman codes,
4606
+ * allowing for a simpler decoder for specialized applications.
4607
+ */
4608
+ rb_define_const(mZlib, "FIXED", INT2FIX(Z_FIXED));
4609
+ #endif
4610
+
4611
+ /* Default deflate strategy which is used for normal data. */
4612
+ rb_define_const(mZlib, "DEFAULT_STRATEGY", INT2FIX(Z_DEFAULT_STRATEGY));
4613
+
4614
+ /* The maximum size of the zlib history buffer. Note that zlib allows
4615
+ * larger values to enable different inflate modes. See Zstdlib::Inflate.new
4616
+ * for details.
4617
+ */
4618
+ rb_define_const(mZlib, "MAX_WBITS", INT2FIX(MAX_WBITS));
4619
+
4620
+ /* The default memory level for allocating zlib deflate compression state.
4621
+ */
4622
+ rb_define_const(mZlib, "DEF_MEM_LEVEL", INT2FIX(DEF_MEM_LEVEL));
4623
+
4624
+ /* The maximum memory level for allocating zlib deflate compression state.
4625
+ */
4626
+ rb_define_const(mZlib, "MAX_MEM_LEVEL", INT2FIX(MAX_MEM_LEVEL));
4627
+
4628
+ /* NO_FLUSH is the default flush method and allows deflate to decide how
4629
+ * much data to accumulate before producing output in order to maximize
4630
+ * compression.
4631
+ */
4632
+ rb_define_const(mZlib, "NO_FLUSH", INT2FIX(Z_NO_FLUSH));
4633
+
4634
+ /* The SYNC_FLUSH method flushes all pending output to the output buffer
4635
+ * and the output is aligned on a byte boundary. Flushing may degrade
4636
+ * compression so it should be used only when necessary, such as at a
4637
+ * request or response boundary for a network stream.
4638
+ */
4639
+ rb_define_const(mZlib, "SYNC_FLUSH", INT2FIX(Z_SYNC_FLUSH));
4640
+
4641
+ /* Flushes all output as with SYNC_FLUSH, and the compression state is
4642
+ * reset so that decompression can restart from this point if previous
4643
+ * compressed data has been damaged or if random access is desired. Like
4644
+ * SYNC_FLUSH, using FULL_FLUSH too often can seriously degrade
4645
+ * compression.
4646
+ */
4647
+ rb_define_const(mZlib, "FULL_FLUSH", INT2FIX(Z_FULL_FLUSH));
4648
+
4649
+ /* Processes all pending input and flushes pending output. */
4650
+ rb_define_const(mZlib, "FINISH", INT2FIX(Z_FINISH));
4651
+
4652
+ #if GZIP_SUPPORT
4653
+ id_write = rb_intern("write");
4654
+ id_read = rb_intern("read");
4655
+ id_readpartial = rb_intern("readpartial");
4656
+ id_flush = rb_intern("flush");
4657
+ id_seek = rb_intern("seek");
4658
+ id_close = rb_intern("close");
4659
+ id_path = rb_intern("path");
4660
+ id_input = rb_intern("@input");
4661
+
4662
+ cGzipFile = rb_define_class_under(mZlib, "GzipFile", rb_cObject);
4663
+ cGzError = rb_define_class_under(cGzipFile, "Error", cZError);
4664
+
4665
+ /* input gzipped string */
4666
+ rb_define_attr(cGzError, "input", 1, 0);
4667
+ rb_define_method(cGzError, "inspect", gzfile_error_inspect, 0);
4668
+
4669
+ cNoFooter = rb_define_class_under(cGzipFile, "NoFooter", cGzError);
4670
+ cCRCError = rb_define_class_under(cGzipFile, "CRCError", cGzError);
4671
+ cLengthError = rb_define_class_under(cGzipFile,"LengthError",cGzError);
4672
+
4673
+ cGzipWriter = rb_define_class_under(mZlib, "GzipWriter", cGzipFile);
4674
+ cGzipReader = rb_define_class_under(mZlib, "GzipReader", cGzipFile);
4675
+ rb_include_module(cGzipReader, rb_mEnumerable);
4676
+
4677
+ rb_define_singleton_method(cGzipFile, "wrap", rb_gzfile_s_wrap, -1);
4678
+ rb_undef_alloc_func(cGzipFile);
4679
+ rb_define_method(cGzipFile, "to_io", rb_gzfile_to_io, 0);
4680
+ rb_define_method(cGzipFile, "crc", rb_gzfile_crc, 0);
4681
+ rb_define_method(cGzipFile, "mtime", rb_gzfile_mtime, 0);
4682
+ rb_define_method(cGzipFile, "level", rb_gzfile_level, 0);
4683
+ rb_define_method(cGzipFile, "os_code", rb_gzfile_os_code, 0);
4684
+ rb_define_method(cGzipFile, "orig_name", rb_gzfile_orig_name, 0);
4685
+ rb_define_method(cGzipFile, "comment", rb_gzfile_comment, 0);
4686
+ rb_define_method(cGzipReader, "lineno", rb_gzfile_lineno, 0);
4687
+ rb_define_method(cGzipReader, "lineno=", rb_gzfile_set_lineno, 1);
4688
+ rb_define_method(cGzipWriter, "mtime=", rb_gzfile_set_mtime, 1);
4689
+ rb_define_method(cGzipWriter, "orig_name=", rb_gzfile_set_orig_name,1);
4690
+ rb_define_method(cGzipWriter, "comment=", rb_gzfile_set_comment, 1);
4691
+ rb_define_method(cGzipFile, "close", rb_gzfile_close, 0);
4692
+ rb_define_method(cGzipFile, "finish", rb_gzfile_finish, 0);
4693
+ rb_define_method(cGzipFile, "closed?", rb_gzfile_closed_p, 0);
4694
+ rb_define_method(cGzipReader, "eof", rb_gzfile_eof_p, 0);
4695
+ rb_define_method(cGzipReader, "eof?", rb_gzfile_eof_p, 0);
4696
+ rb_define_method(cGzipFile, "sync", rb_gzfile_sync, 0);
4697
+ rb_define_method(cGzipFile, "sync=", rb_gzfile_set_sync, 1);
4698
+ rb_define_method(cGzipReader, "pos", rb_gzfile_total_out, 0);
4699
+ rb_define_method(cGzipWriter, "pos", rb_gzfile_total_in, 0);
4700
+ rb_define_method(cGzipReader, "tell", rb_gzfile_total_out, 0);
4701
+ rb_define_method(cGzipWriter, "tell", rb_gzfile_total_in, 0);
4702
+
4703
+ rb_define_singleton_method(cGzipWriter, "open", rb_gzwriter_s_open,-1);
4704
+ rb_define_alloc_func(cGzipWriter, rb_gzwriter_s_allocate);
4705
+ rb_define_method(cGzipWriter, "initialize", rb_gzwriter_initialize,-1);
4706
+ rb_define_method(cGzipWriter, "flush", rb_gzwriter_flush, -1);
4707
+ rb_define_method(cGzipWriter, "write", rb_gzwriter_write, -1);
4708
+ rb_define_method(cGzipWriter, "putc", rb_gzwriter_putc, 1);
4709
+ rb_define_method(cGzipWriter, "<<", rb_gzwriter_addstr, 1);
4710
+ rb_define_method(cGzipWriter, "printf", rb_gzwriter_printf, -1);
4711
+ rb_define_method(cGzipWriter, "print", rb_gzwriter_print, -1);
4712
+ rb_define_method(cGzipWriter, "puts", rb_gzwriter_puts, -1);
4713
+
4714
+ rb_define_singleton_method(cGzipReader, "open", rb_gzreader_s_open,-1);
4715
+ rb_define_alloc_func(cGzipReader, rb_gzreader_s_allocate);
4716
+ rb_define_method(cGzipReader, "initialize", rb_gzreader_initialize, -1);
4717
+ rb_define_method(cGzipReader, "rewind", rb_gzreader_rewind, 0);
4718
+ rb_define_method(cGzipReader, "unused", rb_gzreader_unused, 0);
4719
+ rb_define_method(cGzipReader, "read", rb_gzreader_read, -1);
4720
+ rb_define_method(cGzipReader, "readpartial", rb_gzreader_readpartial, -1);
4721
+ rb_define_method(cGzipReader, "getc", rb_gzreader_getc, 0);
4722
+ rb_define_method(cGzipReader, "getbyte", rb_gzreader_getbyte, 0);
4723
+ rb_define_method(cGzipReader, "readchar", rb_gzreader_readchar, 0);
4724
+ rb_define_method(cGzipReader, "readbyte", rb_gzreader_readbyte, 0);
4725
+ rb_define_method(cGzipReader, "each_byte", rb_gzreader_each_byte, 0);
4726
+ rb_define_method(cGzipReader, "each_char", rb_gzreader_each_char, 0);
4727
+ rb_define_method(cGzipReader, "bytes", rb_gzreader_bytes, 0);
4728
+ rb_define_method(cGzipReader, "ungetc", rb_gzreader_ungetc, 1);
4729
+ rb_define_method(cGzipReader, "ungetbyte", rb_gzreader_ungetbyte, 1);
4730
+ rb_define_method(cGzipReader, "gets", rb_gzreader_gets, -1);
4731
+ rb_define_method(cGzipReader, "readline", rb_gzreader_readline, -1);
4732
+ rb_define_method(cGzipReader, "each", rb_gzreader_each, -1);
4733
+ rb_define_method(cGzipReader, "each_line", rb_gzreader_each, -1);
4734
+ rb_define_method(cGzipReader, "lines", rb_gzreader_lines, -1);
4735
+ rb_define_method(cGzipReader, "readlines", rb_gzreader_readlines, -1);
4736
+ rb_define_method(cGzipReader, "external_encoding", rb_gzreader_external_encoding, 0);
4737
+
4738
+ rb_define_singleton_method(mZlib, "gzip", zlib_s_gzip, -1);
4739
+ rb_define_singleton_method(mZlib, "gunzip", zlib_gunzip, 1);
4740
+
4741
+ /* The OS code of current host */
4742
+ rb_define_const(mZlib, "OS_CODE", INT2FIX(OS_CODE));
4743
+ /* OS code for MSDOS hosts */
4744
+ rb_define_const(mZlib, "OS_MSDOS", INT2FIX(OS_MSDOS));
4745
+ /* OS code for Amiga hosts */
4746
+ rb_define_const(mZlib, "OS_AMIGA", INT2FIX(OS_AMIGA));
4747
+ /* OS code for VMS hosts */
4748
+ rb_define_const(mZlib, "OS_VMS", INT2FIX(OS_VMS));
4749
+ /* OS code for UNIX hosts */
4750
+ rb_define_const(mZlib, "OS_UNIX", INT2FIX(OS_UNIX));
4751
+ /* OS code for Atari hosts */
4752
+ rb_define_const(mZlib, "OS_ATARI", INT2FIX(OS_ATARI));
4753
+ /* OS code for OS2 hosts */
4754
+ rb_define_const(mZlib, "OS_OS2", INT2FIX(OS_OS2));
4755
+ /* OS code for Mac OS hosts */
4756
+ rb_define_const(mZlib, "OS_MACOS", INT2FIX(OS_MACOS));
4757
+ /* OS code for TOPS-20 hosts */
4758
+ rb_define_const(mZlib, "OS_TOPS20", INT2FIX(OS_TOPS20));
4759
+ /* OS code for Win32 hosts */
4760
+ rb_define_const(mZlib, "OS_WIN32", INT2FIX(OS_WIN32));
4761
+ /* OS code for VM OS hosts */
4762
+ rb_define_const(mZlib, "OS_VMCMS", INT2FIX(OS_VMCMS));
4763
+ /* OS code for Z-System hosts */
4764
+ rb_define_const(mZlib, "OS_ZSYSTEM", INT2FIX(OS_ZSYSTEM));
4765
+ /* OS code for CP/M hosts */
4766
+ rb_define_const(mZlib, "OS_CPM", INT2FIX(OS_CPM));
4767
+ /* OS code for QDOS hosts */
4768
+ rb_define_const(mZlib, "OS_QDOS", INT2FIX(OS_QDOS));
4769
+ /* OS code for RISC OS hosts */
4770
+ rb_define_const(mZlib, "OS_RISCOS", INT2FIX(OS_RISCOS));
4771
+ /* OS code for unknown hosts */
4772
+ rb_define_const(mZlib, "OS_UNKNOWN", INT2FIX(OS_UNKNOWN));
4773
+
4774
+ id_level = rb_intern("level");
4775
+ id_strategy = rb_intern("strategy");
4776
+ #endif /* GZIP_SUPPORT */
4777
+ }
4778
+
4779
+ /* Document error classes. */
4780
+
4781
+ /*
4782
+ * Document-class: Zstdlib::Error
4783
+ *
4784
+ * The superclass for all exceptions raised by Ruby/zlib.
4785
+ *
4786
+ * The following exceptions are defined as subclasses of Zstdlib::Error. These
4787
+ * exceptions are raised when zlib library functions return with an error
4788
+ * status.
4789
+ *
4790
+ * - Zstdlib::StreamEnd
4791
+ * - Zstdlib::NeedDict
4792
+ * - Zstdlib::DataError
4793
+ * - Zstdlib::StreamError
4794
+ * - Zstdlib::MemError
4795
+ * - Zstdlib::BufError
4796
+ * - Zstdlib::VersionError
4797
+ *
4798
+ */
4799
+
4800
+ /*
4801
+ * Document-class: Zstdlib::StreamEnd
4802
+ *
4803
+ * Subclass of Zstdlib::Error
4804
+ *
4805
+ * When zlib returns a Z_STREAM_END
4806
+ * is return if the end of the compressed data has been reached
4807
+ * and all uncompressed out put has been produced.
4808
+ *
4809
+ */
4810
+
4811
+ /*
4812
+ * Document-class: Zstdlib::NeedDict
4813
+ *
4814
+ * Subclass of Zstdlib::Error
4815
+ *
4816
+ * When zlib returns a Z_NEED_DICT
4817
+ * if a preset dictionary is needed at this point.
4818
+ *
4819
+ * Used by Zstdlib::Inflate.inflate and <tt>Zstdlib.inflate</tt>
4820
+ */
4821
+
4822
+ /*
4823
+ * Document-class: Zstdlib::VersionError
4824
+ *
4825
+ * Subclass of Zstdlib::Error
4826
+ *
4827
+ * When zlib returns a Z_VERSION_ERROR,
4828
+ * usually if the zlib library version is incompatible with the
4829
+ * version assumed by the caller.
4830
+ *
4831
+ */
4832
+
4833
+ /*
4834
+ * Document-class: Zstdlib::MemError
4835
+ *
4836
+ * Subclass of Zstdlib::Error
4837
+ *
4838
+ * When zlib returns a Z_MEM_ERROR,
4839
+ * usually if there was not enough memory.
4840
+ *
4841
+ */
4842
+
4843
+ /*
4844
+ * Document-class: Zstdlib::StreamError
4845
+ *
4846
+ * Subclass of Zstdlib::Error
4847
+ *
4848
+ * When zlib returns a Z_STREAM_ERROR,
4849
+ * usually if the stream state was inconsistent.
4850
+ *
4851
+ */
4852
+
4853
+ /*
4854
+ * Document-class: Zstdlib::BufError
4855
+ *
4856
+ * Subclass of Zstdlib::Error when zlib returns a Z_BUF_ERROR.
4857
+ *
4858
+ * Usually if no progress is possible.
4859
+ *
4860
+ */
4861
+
4862
+ /*
4863
+ * Document-class: Zstdlib::DataError
4864
+ *
4865
+ * Subclass of Zstdlib::Error when zlib returns a Z_DATA_ERROR.
4866
+ *
4867
+ * Usually if a stream was prematurely freed.
4868
+ *
4869
+ */
4870
+
4871
+ /*
4872
+ * Document-class: Zstdlib::GzipFile::Error
4873
+ *
4874
+ * Base class of errors that occur when processing GZIP files.
4875
+ */
4876
+
4877
+ /*
4878
+ * Document-class: Zstdlib::GzipFile::NoFooter
4879
+ *
4880
+ * Raised when gzip file footer is not found.
4881
+ */
4882
+
4883
+ /*
4884
+ * Document-class: Zstdlib::GzipFile::CRCError
4885
+ *
4886
+ * Raised when the CRC checksum recorded in gzip file footer is not equivalent
4887
+ * to the CRC checksum of the actual uncompressed data.
4888
+ */
4889
+
4890
+ /*
4891
+ * Document-class: Zstdlib::GzipFile::LengthError
4892
+ *
4893
+ * Raised when the data length recorded in the gzip file footer is not equivalent
4894
+ * to the length of the actual uncompressed data.
4895
+ */