zstdlib 0.6.0-x64-mingw32 → 0.9.0-x64-mingw32

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