extzstd 0.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. checksums.yaml +5 -5
  2. data/HISTORY.ja.md +39 -0
  3. data/README.md +38 -56
  4. data/contrib/zstd/CHANGELOG +613 -0
  5. data/contrib/zstd/CODE_OF_CONDUCT.md +5 -0
  6. data/contrib/zstd/CONTRIBUTING.md +406 -0
  7. data/contrib/zstd/COPYING +339 -0
  8. data/contrib/zstd/Makefile +420 -0
  9. data/contrib/zstd/README.md +179 -41
  10. data/contrib/zstd/TESTING.md +44 -0
  11. data/contrib/zstd/appveyor.yml +292 -0
  12. data/contrib/zstd/lib/BUCK +234 -0
  13. data/contrib/zstd/lib/Makefile +451 -0
  14. data/contrib/zstd/lib/README.md +207 -0
  15. data/contrib/zstd/{common → lib/common}/bitstream.h +187 -138
  16. data/contrib/zstd/lib/common/compiler.h +288 -0
  17. data/contrib/zstd/lib/common/cpu.h +213 -0
  18. data/contrib/zstd/lib/common/debug.c +24 -0
  19. data/contrib/zstd/lib/common/debug.h +107 -0
  20. data/contrib/zstd/lib/common/entropy_common.c +362 -0
  21. data/contrib/zstd/{common → lib/common}/error_private.c +25 -12
  22. data/contrib/zstd/{common → lib/common}/error_private.h +14 -10
  23. data/contrib/zstd/{common → lib/common}/fse.h +173 -92
  24. data/contrib/zstd/{common → lib/common}/fse_decompress.c +149 -85
  25. data/contrib/zstd/lib/common/huf.h +361 -0
  26. data/contrib/zstd/{common → lib/common}/mem.h +115 -59
  27. data/contrib/zstd/lib/common/pool.c +350 -0
  28. data/contrib/zstd/lib/common/pool.h +84 -0
  29. data/contrib/zstd/lib/common/threading.c +122 -0
  30. data/contrib/zstd/lib/common/threading.h +155 -0
  31. data/contrib/zstd/{common → lib/common}/xxhash.c +55 -96
  32. data/contrib/zstd/{common → lib/common}/xxhash.h +23 -47
  33. data/contrib/zstd/lib/common/zstd_common.c +83 -0
  34. data/contrib/zstd/lib/common/zstd_deps.h +111 -0
  35. data/contrib/zstd/lib/common/zstd_errors.h +95 -0
  36. data/contrib/zstd/lib/common/zstd_internal.h +478 -0
  37. data/contrib/zstd/{compress → lib/compress}/fse_compress.c +214 -319
  38. data/contrib/zstd/lib/compress/hist.c +181 -0
  39. data/contrib/zstd/lib/compress/hist.h +75 -0
  40. data/contrib/zstd/lib/compress/huf_compress.c +913 -0
  41. data/contrib/zstd/lib/compress/zstd_compress.c +5208 -0
  42. data/contrib/zstd/lib/compress/zstd_compress_internal.h +1203 -0
  43. data/contrib/zstd/lib/compress/zstd_compress_literals.c +158 -0
  44. data/contrib/zstd/lib/compress/zstd_compress_literals.h +29 -0
  45. data/contrib/zstd/lib/compress/zstd_compress_sequences.c +433 -0
  46. data/contrib/zstd/lib/compress/zstd_compress_sequences.h +54 -0
  47. data/contrib/zstd/lib/compress/zstd_compress_superblock.c +849 -0
  48. data/contrib/zstd/lib/compress/zstd_compress_superblock.h +32 -0
  49. data/contrib/zstd/lib/compress/zstd_cwksp.h +561 -0
  50. data/contrib/zstd/lib/compress/zstd_double_fast.c +521 -0
  51. data/contrib/zstd/lib/compress/zstd_double_fast.h +38 -0
  52. data/contrib/zstd/lib/compress/zstd_fast.c +496 -0
  53. data/contrib/zstd/lib/compress/zstd_fast.h +37 -0
  54. data/contrib/zstd/lib/compress/zstd_lazy.c +1412 -0
  55. data/contrib/zstd/lib/compress/zstd_lazy.h +87 -0
  56. data/contrib/zstd/lib/compress/zstd_ldm.c +660 -0
  57. data/contrib/zstd/lib/compress/zstd_ldm.h +116 -0
  58. data/contrib/zstd/lib/compress/zstd_opt.c +1345 -0
  59. data/contrib/zstd/lib/compress/zstd_opt.h +56 -0
  60. data/contrib/zstd/lib/compress/zstdmt_compress.c +1811 -0
  61. data/contrib/zstd/lib/compress/zstdmt_compress.h +110 -0
  62. data/contrib/zstd/lib/decompress/huf_decompress.c +1350 -0
  63. data/contrib/zstd/lib/decompress/zstd_ddict.c +244 -0
  64. data/contrib/zstd/lib/decompress/zstd_ddict.h +44 -0
  65. data/contrib/zstd/lib/decompress/zstd_decompress.c +1930 -0
  66. data/contrib/zstd/lib/decompress/zstd_decompress_block.c +1540 -0
  67. data/contrib/zstd/lib/decompress/zstd_decompress_block.h +62 -0
  68. data/contrib/zstd/lib/decompress/zstd_decompress_internal.h +190 -0
  69. data/contrib/zstd/{common → lib/deprecated}/zbuff.h +68 -45
  70. data/contrib/zstd/lib/deprecated/zbuff_common.c +26 -0
  71. data/contrib/zstd/lib/deprecated/zbuff_compress.c +147 -0
  72. data/contrib/zstd/lib/deprecated/zbuff_decompress.c +75 -0
  73. data/contrib/zstd/lib/dictBuilder/cover.c +1245 -0
  74. data/contrib/zstd/lib/dictBuilder/cover.h +157 -0
  75. data/contrib/zstd/{dictBuilder → lib/dictBuilder}/divsufsort.c +3 -3
  76. data/contrib/zstd/{dictBuilder → lib/dictBuilder}/divsufsort.h +0 -0
  77. data/contrib/zstd/lib/dictBuilder/fastcover.c +758 -0
  78. data/contrib/zstd/{dictBuilder → lib/dictBuilder}/zdict.c +318 -194
  79. data/contrib/zstd/lib/dictBuilder/zdict.h +305 -0
  80. data/contrib/zstd/{legacy → lib/legacy}/zstd_legacy.h +171 -15
  81. data/contrib/zstd/{legacy → lib/legacy}/zstd_v01.c +191 -124
  82. data/contrib/zstd/{legacy → lib/legacy}/zstd_v01.h +19 -5
  83. data/contrib/zstd/{legacy → lib/legacy}/zstd_v02.c +125 -125
  84. data/contrib/zstd/{legacy → lib/legacy}/zstd_v02.h +19 -5
  85. data/contrib/zstd/{legacy → lib/legacy}/zstd_v03.c +125 -124
  86. data/contrib/zstd/{legacy → lib/legacy}/zstd_v03.h +20 -6
  87. data/contrib/zstd/{legacy → lib/legacy}/zstd_v04.c +151 -299
  88. data/contrib/zstd/{legacy → lib/legacy}/zstd_v04.h +19 -5
  89. data/contrib/zstd/{legacy → lib/legacy}/zstd_v05.c +237 -243
  90. data/contrib/zstd/{legacy → lib/legacy}/zstd_v05.h +19 -6
  91. data/contrib/zstd/{legacy → lib/legacy}/zstd_v06.c +130 -143
  92. data/contrib/zstd/{legacy → lib/legacy}/zstd_v06.h +18 -5
  93. data/contrib/zstd/{legacy → lib/legacy}/zstd_v07.c +158 -157
  94. data/contrib/zstd/{legacy → lib/legacy}/zstd_v07.h +19 -5
  95. data/contrib/zstd/lib/libzstd.pc.in +15 -0
  96. data/contrib/zstd/lib/zstd.h +2391 -0
  97. data/ext/depend +2 -0
  98. data/ext/extconf.rb +15 -6
  99. data/ext/extzstd.c +76 -145
  100. data/ext/extzstd.h +80 -31
  101. data/ext/extzstd_stream.c +417 -142
  102. data/ext/libzstd_conf.h +8 -0
  103. data/ext/zstd_common.c +10 -7
  104. data/ext/zstd_compress.c +14 -5
  105. data/ext/zstd_decompress.c +5 -4
  106. data/ext/zstd_dictbuilder.c +9 -4
  107. data/ext/zstd_dictbuilder_fastcover.c +3 -0
  108. data/ext/zstd_legacy_v01.c +3 -1
  109. data/ext/zstd_legacy_v02.c +3 -1
  110. data/ext/zstd_legacy_v03.c +3 -1
  111. data/ext/zstd_legacy_v04.c +3 -1
  112. data/ext/zstd_legacy_v05.c +3 -1
  113. data/ext/zstd_legacy_v06.c +3 -1
  114. data/ext/zstd_legacy_v07.c +3 -1
  115. data/gemstub.rb +10 -24
  116. data/lib/extzstd.rb +64 -179
  117. data/lib/extzstd/version.rb +6 -1
  118. data/test/test_basic.rb +9 -6
  119. metadata +113 -57
  120. data/HISTORY.ja +0 -5
  121. data/contrib/zstd/common/entropy_common.c +0 -225
  122. data/contrib/zstd/common/huf.h +0 -228
  123. data/contrib/zstd/common/zstd_common.c +0 -83
  124. data/contrib/zstd/common/zstd_errors.h +0 -60
  125. data/contrib/zstd/common/zstd_internal.h +0 -267
  126. data/contrib/zstd/compress/huf_compress.c +0 -533
  127. data/contrib/zstd/compress/zbuff_compress.c +0 -319
  128. data/contrib/zstd/compress/zstd_compress.c +0 -3264
  129. data/contrib/zstd/compress/zstd_opt.h +0 -900
  130. data/contrib/zstd/decompress/huf_decompress.c +0 -883
  131. data/contrib/zstd/decompress/zbuff_decompress.c +0 -252
  132. data/contrib/zstd/decompress/zstd_decompress.c +0 -1842
  133. data/contrib/zstd/dictBuilder/zdict.h +0 -111
  134. data/contrib/zstd/zstd.h +0 -640
data/ext/extzstd_stream.c CHANGED
@@ -2,48 +2,97 @@
2
2
  #include "extzstd_nogvls.h"
3
3
  #include <errno.h>
4
4
 
5
+ enum {
6
+ EXT_PARTIAL_READ_SIZE = 256 * 1024, /* 256 KiB */
7
+ EXT_READ_GROWUP_SIZE = 256 * 1024, /* 256 KiB */
8
+ EXT_READ_DOUBLE_GROWUP_LIMIT_SIZE = 4 * 1024 * 1024, /* 4 MiB */
9
+ };
10
+
11
+ static inline VALUE
12
+ aux_str_buf_recycle(VALUE str, size_t capacity)
13
+ {
14
+ if (!RTEST(str) || rb_obj_frozen_p(str) || !rb_type_p(str, RUBY_T_STRING)) {
15
+ return rb_str_buf_new(capacity);
16
+ } else {
17
+ return aux_str_modify_expand(str, capacity);
18
+ }
19
+ }
20
+
21
+ static ID id_op_lsh, id_read;
22
+
5
23
  /*
6
- * class Zstd::StreamEncoder
24
+ * class Zstd::Encoder
7
25
  */
8
26
 
9
27
  static VALUE cStreamEncoder;
10
28
 
29
+ struct encoder
30
+ {
31
+ ZSTD_CStream *context;
32
+ VALUE outport;
33
+ VALUE predict;
34
+ VALUE destbuf;
35
+ int reached_eof;
36
+ };
37
+
11
38
  static void
12
- enc_free(void *p)
39
+ enc_gc_mark(void *pp)
13
40
  {
14
- ZSTD_freeCStream(p);
41
+ if (pp) {
42
+ struct encoder *p = (struct encoder *)pp;
43
+ rb_gc_mark(p->outport);
44
+ rb_gc_mark(p->predict);
45
+ rb_gc_mark(p->destbuf);
46
+ }
47
+ }
48
+
49
+ static void
50
+ enc_free(void *pp)
51
+ {
52
+ if (pp) {
53
+ struct encoder *p = (struct encoder *)pp;
54
+ if (p->context) {
55
+ ZSTD_freeCStream(p->context);
56
+ p->context = NULL;
57
+ }
58
+ xfree(p);
59
+ }
15
60
  }
16
61
 
17
62
  AUX_IMPLEMENT_CONTEXT(
18
- ZSTD_CStream, encoder_type, "extzstd.Zstd::StreamEncoder",
19
- encoder_alloc_dummy, NULL, enc_free, NULL,
63
+ struct encoder, encoder_type, "extzstd.Zstd::Encoder",
64
+ encoder_alloc_dummy, enc_gc_mark, enc_free, NULL,
20
65
  getencoderp, getencoder, encoder_p);
21
66
 
22
67
  static VALUE
23
68
  enc_alloc(VALUE mod)
24
69
  {
25
- VALUE obj = TypedData_Wrap_Struct(mod, &encoder_type, NULL);
26
-
27
- ZSTD_CStream *p = ZSTD_createCStream();
28
- if (!p) {
29
- rb_gc();
30
- p = ZSTD_createCStream();
31
- if (!p) {
32
- errno = ENOMEM;
33
- rb_sys_fail("failed ZSTD_createCStream()");
34
- }
35
- }
36
- DATA_PTR(obj) = p;
37
-
70
+ struct encoder *p;
71
+ VALUE obj = TypedData_Make_Struct(mod, struct encoder, &encoder_type, p);
72
+ p->outport = Qnil;
73
+ p->predict = Qnil;
74
+ p->destbuf = Qnil;
38
75
  return obj;
39
76
  }
40
77
 
78
+ static struct encoder *
79
+ encoder_context(VALUE self)
80
+ {
81
+ struct encoder *p = getencoder(self);
82
+ if (!p->context) {
83
+ rb_raise(rb_eTypeError,
84
+ "wrong initialized context - #<%s:%p>",
85
+ rb_obj_classname(self), (void *)self);
86
+ }
87
+ return p;
88
+ }
89
+
41
90
  /*
42
91
  * call-seq:
43
- * initialize(compression_parameters, predict)
92
+ * initialize(outport, compression_parameters = nil, predict = nil)
44
93
  */
45
94
  static VALUE
46
- enc_init(VALUE self, VALUE params, VALUE predict)
95
+ enc_init(int argc, VALUE argv[], VALUE self)
47
96
  {
48
97
  /*
49
98
  * ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel);
@@ -52,7 +101,37 @@ enc_init(VALUE self, VALUE params, VALUE predict)
52
101
  * ZSTD_parameters params, unsigned long long pledgedSrcSize);
53
102
  */
54
103
 
55
- ZSTD_CStream *p = getencoder(self);
104
+ VALUE outport, params, predict;
105
+ switch (argc) {
106
+ case 1:
107
+ outport = argv[0];
108
+ params = predict = Qnil;
109
+ break;
110
+ case 2:
111
+ outport = argv[0];
112
+ params = argv[1];
113
+ predict = Qnil;
114
+ break;
115
+ case 3:
116
+ outport = argv[0];
117
+ params = argv[1];
118
+ predict = argv[2];
119
+ break;
120
+ default:
121
+ rb_error_arity(argc, 1, 3);
122
+ }
123
+
124
+ struct encoder *p = getencoder(self);
125
+ if (p->context) {
126
+ rb_raise(rb_eTypeError,
127
+ "initialized already - #<%s:%p>",
128
+ rb_obj_classname(self), (void *)self);
129
+ }
130
+
131
+ AUX_TRY_WITH_GC(
132
+ p->context = ZSTD_createCStream(),
133
+ "failed ZSTD_createCStream()");
134
+
56
135
  const void *predictp;
57
136
  size_t predictsize;
58
137
  if (NIL_P(predict)) {
@@ -60,107 +139,102 @@ enc_init(VALUE self, VALUE params, VALUE predict)
60
139
  predictsize = 0;
61
140
  } else {
62
141
  rb_check_type(predict, RUBY_T_STRING);
142
+ predict = rb_str_new_frozen(predict);
63
143
  RSTRING_GETMEM(predict, predictp, predictsize);
64
144
  }
65
145
 
66
146
  if (extzstd_params_p(params)) {
67
147
  ZSTD_parameters *paramsp = extzstd_getparams(params);
68
- size_t s = ZSTD_initCStream_advanced(p, predictp, predictsize, *paramsp, 0);
148
+ size_t s = ZSTD_initCStream_advanced(p->context, predictp, predictsize, *paramsp, -1);
69
149
  extzstd_check_error(s);
70
150
  } else {
71
- size_t s = ZSTD_initCStream_usingDict(p, predictp, predictsize, aux_num2int(params, 1));
151
+ size_t s = ZSTD_initCStream_usingDict(p->context, predictp, predictsize, aux_num2int(params, 1));
72
152
  extzstd_check_error(s);
73
153
  }
154
+
155
+ p->predict = predict;
156
+ p->outport = outport;
157
+
74
158
  return self;
75
159
  }
76
160
 
77
161
  static VALUE
78
- enc_update(VALUE self, VALUE src, VALUE srcoff, VALUE dest, VALUE maxdest)
162
+ enc_write(VALUE self, VALUE src)
79
163
  {
80
164
  /*
81
165
  * ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
82
166
  */
83
167
 
84
- ZSTD_CStream *p = getencoder(self);
168
+ struct encoder *p = encoder_context(self);
169
+ src = rb_String(src);
170
+ ZSTD_inBuffer input = { RSTRING_PTR(src), RSTRING_LEN(src), 0 };
171
+
172
+ while (input.pos < input.size) {
173
+ p->destbuf = aux_str_buf_recycle(p->destbuf, ZSTD_CStreamOutSize() * 2);
174
+ rb_str_set_len(p->destbuf, 0);
175
+ rb_obj_infect(self, src);
176
+ rb_obj_infect(p->destbuf, self);
177
+ ZSTD_outBuffer output = { RSTRING_PTR(p->destbuf), rb_str_capacity(p->destbuf), 0 };
178
+ size_t s = ZSTD_compressStream(p->context, &output, &input);
179
+ extzstd_check_error(s);
180
+ rb_str_set_len(p->destbuf, output.pos);
85
181
 
86
- rb_check_type(src, RUBY_T_STRING);
87
- const char *q = RSTRING_PTR(src);
88
- const char *qq = RSTRING_END(src);
89
- const char *q1 = q + NUM2SIZET(srcoff);
90
- if (q1 < q || q1 > qq) {
91
- rb_raise(rb_eArgError,
92
- "``srcoff'' is out of range (given %"PRIuSIZE", expect 0..%"PRIuSIZE")",
93
- q1 - q, qq - q);
182
+ // TODO: 例外や帯域脱出した場合の挙動は?
183
+ // TODO: src の途中経過状態を保存するべきか?
184
+ AUX_FUNCALL(p->outport, id_op_lsh, p->destbuf);
94
185
  }
95
186
 
96
- rb_check_type(dest, RUBY_T_STRING);
97
- rb_str_modify(dest);
98
- rb_str_set_len(dest, 0);
99
- rb_str_modify_expand(dest, NUM2SIZET(maxdest));
100
- rb_obj_infect(self, src);
101
- rb_obj_infect(dest, self);
102
- char *r = RSTRING_PTR(dest);
103
- const char *rr = r + rb_str_capacity(dest);
104
-
105
- ZSTD_inBuffer input = { q, qq - q, q1 - q };
106
- ZSTD_outBuffer output = { r, rr - r, 0 };
107
- size_t s = ZSTD_compressStream(p, &output, &input);
108
- extzstd_check_error(s);
109
- rb_str_set_len(dest, output.pos);
110
- if (input.pos == input.size) {
111
- return Qnil;
112
- } else {
113
- return SIZET2NUM(input.pos);
114
- }
187
+ return self;
115
188
  }
116
189
 
117
190
  static VALUE
118
- enc_flush(VALUE self, VALUE dest, VALUE maxdest)
191
+ enc_sync(VALUE self)
119
192
  {
120
193
  /*
121
194
  * ZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
122
195
  */
123
196
 
124
- ZSTD_CStream *p = getencoder(self);
197
+ struct encoder *p = encoder_context(self);
198
+ aux_str_buf_recycle(p->destbuf, ZSTD_CStreamOutSize());
199
+ rb_str_set_len(p->destbuf, 0);
200
+ rb_obj_infect(p->destbuf, self);
201
+ ZSTD_outBuffer output = { RSTRING_PTR(p->destbuf), rb_str_capacity(p->destbuf), 0 };
202
+ size_t s = ZSTD_flushStream(p->context, &output);
203
+ extzstd_check_error(s);
204
+ rb_str_set_len(p->destbuf, output.pos);
125
205
 
126
- rb_check_type(dest, RUBY_T_STRING);
127
- rb_str_modify(dest);
128
- rb_str_set_len(dest, 0);
129
- rb_str_modify_expand(dest, NUM2SIZET(maxdest));
206
+ AUX_FUNCALL(p->outport, id_op_lsh, p->destbuf);
130
207
 
131
- ZSTD_outBuffer output = { RSTRING_PTR(dest), rb_str_capacity(dest), 0 };
132
- size_t s = ZSTD_flushStream(p, &output);
133
- extzstd_check_error(s);
134
- if (output.size > 0) {
135
- rb_str_set_len(dest, output.pos);
136
- return dest;
137
- } else {
138
- return Qnil;
139
- }
208
+ return self;
140
209
  }
141
210
 
142
211
  static VALUE
143
- enc_end(VALUE self, VALUE dest, VALUE maxdest)
212
+ enc_close(VALUE self)
144
213
  {
145
214
  /*
146
215
  * ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
147
216
  */
148
217
 
149
- ZSTD_CStream *p = getencoder(self);
150
- rb_check_type(dest, RUBY_T_STRING);
151
- rb_str_modify(dest);
152
- rb_str_set_len(dest, 0);
153
- rb_str_modify_expand(dest, NUM2SIZET(maxdest));
154
-
155
- ZSTD_outBuffer output = { RSTRING_PTR(dest), rb_str_capacity(dest), 0 };
156
- size_t s = ZSTD_endStream(p, &output);
218
+ struct encoder *p = encoder_context(self);
219
+ aux_str_buf_recycle(p->destbuf, ZSTD_CStreamOutSize());
220
+ rb_str_set_len(p->destbuf, 0);
221
+ rb_obj_infect(p->destbuf, self);
222
+ ZSTD_outBuffer output = { RSTRING_PTR(p->destbuf), rb_str_capacity(p->destbuf), 0 };
223
+ size_t s = ZSTD_endStream(p->context, &output);
157
224
  extzstd_check_error(s);
158
- if (output.size > 0) {
159
- rb_str_set_len(dest, output.pos);
160
- return dest;
161
- } else {
162
- return Qnil;
163
- }
225
+ rb_str_set_len(p->destbuf, output.pos);
226
+
227
+ AUX_FUNCALL(p->outport, id_op_lsh, p->destbuf);
228
+
229
+ p->reached_eof = 1;
230
+
231
+ return Qnil;
232
+ }
233
+
234
+ static VALUE
235
+ enc_eof(VALUE self)
236
+ {
237
+ return (encoder_context(self)->reached_eof == 0 ? Qfalse : Qtrue);
164
238
  }
165
239
 
166
240
  static VALUE
@@ -170,7 +244,7 @@ enc_reset(VALUE self, VALUE pledged_srcsize)
170
244
  * ZSTDLIB_API size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
171
245
  */
172
246
 
173
- size_t s = ZSTD_resetCStream(getencoder(self), NUM2ULL(pledged_srcsize));
247
+ size_t s = ZSTD_resetCStream(encoder_context(self)->context, NUM2ULL(pledged_srcsize));
174
248
  extzstd_check_error(s);
175
249
  return self;
176
250
  }
@@ -182,7 +256,7 @@ enc_sizeof(VALUE self)
182
256
  * ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
183
257
  */
184
258
 
185
- size_t s = ZSTD_sizeof_CStream(getencoder(self));
259
+ size_t s = ZSTD_sizeof_CStream(encoder_context(self)->context);
186
260
  extzstd_check_error(s);
187
261
  return SIZET2NUM(s);
188
262
  }
@@ -190,113 +264,300 @@ enc_sizeof(VALUE self)
190
264
  static void
191
265
  init_encoder(void)
192
266
  {
193
- cStreamEncoder = rb_define_class_under(extzstd_mZstd, "StreamEncoder", rb_cObject);
267
+ cStreamEncoder = rb_define_class_under(extzstd_mZstd, "Encoder", rb_cObject);
194
268
  rb_define_alloc_func(cStreamEncoder, enc_alloc);
195
269
  rb_define_const(cStreamEncoder, "INSIZE", SIZET2NUM(ZSTD_CStreamInSize()));
196
270
  rb_define_const(cStreamEncoder, "OUTSIZE", SIZET2NUM(ZSTD_CStreamOutSize()));
197
- rb_define_method(cStreamEncoder, "initialize", enc_init, 2);
198
- rb_define_method(cStreamEncoder, "update", enc_update, 4);
199
- rb_define_method(cStreamEncoder, "flush", enc_flush, 2);
200
- rb_define_method(cStreamEncoder, "end", enc_end, 2);
271
+ rb_define_method(cStreamEncoder, "initialize", enc_init, -1);
272
+ rb_define_method(cStreamEncoder, "write", enc_write, 1);
273
+ rb_define_method(cStreamEncoder, "sync", enc_sync, 0);
274
+ rb_define_method(cStreamEncoder, "close", enc_close, 0);
275
+ rb_define_method(cStreamEncoder, "eof", enc_eof, 0);
276
+ rb_define_alias(cStreamEncoder, "eof?", "eof");
201
277
  rb_define_method(cStreamEncoder, "reset", enc_reset, 1);
202
278
  rb_define_method(cStreamEncoder, "sizeof", enc_sizeof, 0);
279
+ rb_define_alias(cStreamEncoder, "<<", "write");
280
+ rb_define_alias(cStreamEncoder, "update", "write");
281
+ rb_define_alias(cStreamEncoder, "flush", "sync");
282
+ rb_define_alias(cStreamEncoder, "end", "close");
283
+ rb_define_alias(cStreamEncoder, "finish", "close");
203
284
  }
204
285
 
205
286
  /*
206
- * class Zstd::StreamDecoder
287
+ * class Zstd::Decoder
207
288
  */
208
289
 
209
290
  static VALUE cStreamDecoder;
210
291
 
292
+ struct decoder
293
+ {
294
+ ZSTD_DStream *context;
295
+ VALUE inport;
296
+ VALUE readbuf;
297
+ VALUE predict;
298
+ ZSTD_inBuffer inbuf;
299
+ int reached_eof;
300
+ };
301
+
211
302
  static void
212
- dec_free(void *p)
303
+ dec_mark(void *pp)
213
304
  {
214
- ZSTD_freeDStream(p);
305
+ struct decoder *p = (struct decoder *)pp;
306
+ rb_gc_mark(p->inport);
307
+ rb_gc_mark(p->readbuf);
308
+ rb_gc_mark(p->predict);
309
+ }
310
+
311
+ static void
312
+ dec_free(void *pp)
313
+ {
314
+ struct decoder *p = (struct decoder *)pp;
315
+ if (p->context) {
316
+ ZSTD_freeDStream(p->context);
317
+ p->context = NULL;
318
+ }
319
+ xfree(p);
215
320
  }
216
321
 
217
322
  AUX_IMPLEMENT_CONTEXT(
218
- ZSTD_DStream, decoder_type, "extzstd.Zstd::StreamDecoder",
219
- decoder_alloc_dummy, NULL, dec_free, NULL,
323
+ struct decoder, decoder_type, "extzstd.Zstd::Decoder",
324
+ decoder_alloc_dummy, dec_mark, dec_free, NULL,
220
325
  getdecoderp, getdecoder, decoder_p);
221
326
 
222
- static VALUE
223
- dec_alloc(VALUE mod)
327
+ static struct decoder *
328
+ decoder_context(VALUE self)
224
329
  {
225
- VALUE obj = TypedData_Wrap_Struct(mod, &decoder_type, NULL);
226
-
227
- ZSTD_DStream *p = ZSTD_createDStream();
228
- if (!p) {
229
- rb_gc();
230
- p = ZSTD_createDStream();
231
- if (!p) {
232
- errno = ENOMEM;
233
- rb_sys_fail("failed ZSTD_createDStream()");
234
- }
330
+ struct decoder *p = getdecoder(self);
331
+ if (!p->context) {
332
+ rb_raise(rb_eTypeError,
333
+ "uninitialized context - #<%s:%p>",
334
+ rb_obj_classname(self), (void *)self);
235
335
  }
236
- DATA_PTR(obj) = p;
336
+ return p;
337
+ }
237
338
 
339
+ static VALUE
340
+ dec_alloc(VALUE mod)
341
+ {
342
+ struct decoder *p;
343
+ VALUE obj = TypedData_Make_Struct(mod, struct decoder, &decoder_type, p);
238
344
  return obj;
239
345
  }
240
346
 
241
347
  /*
242
348
  * call-seq:
243
- * initialize(predict)
349
+ * initialize(inport, predict = Qnil)
244
350
  */
245
351
  static VALUE
246
- dec_init(VALUE self, VALUE predict)
352
+ dec_init(int argc, VALUE argv[], VALUE self)
247
353
  {
248
354
  /*
249
355
  * ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds);
250
356
  * ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
251
357
  */
252
358
 
253
- ZSTD_DStream *p = getdecoder(self);
359
+ VALUE inport, predict;
360
+
361
+ switch (argc) {
362
+ case 1:
363
+ inport = argv[0];
364
+ predict = Qnil;
365
+ break;
366
+ case 2:
367
+ inport = argv[0];
368
+ predict = argv[1];
369
+ break;
370
+ default:
371
+ rb_error_arity(argc, 1, 2);
372
+ }
373
+
374
+ struct decoder *p = getdecoder(self);
375
+ if (p->context) {
376
+ rb_raise(rb_eTypeError,
377
+ "initialized context already - #<%s:%p>",
378
+ rb_obj_classname(self), (void *)self);
379
+ }
380
+
381
+ AUX_TRY_WITH_GC(
382
+ p->context = ZSTD_createDStream(),
383
+ "failed ZSTD_createDStream()");
254
384
 
255
385
  if (NIL_P(predict)) {
256
- size_t s = ZSTD_initDStream(p);
386
+ size_t s = ZSTD_initDStream(p->context);
257
387
  extzstd_check_error(s);
258
388
  } else {
259
389
  rb_check_type(predict, RUBY_T_STRING);
260
- size_t s = ZSTD_initDStream_usingDict(p, RSTRING_PTR(predict), RSTRING_LEN(predict));
390
+ predict = rb_str_new_frozen(predict);
391
+ size_t s = ZSTD_initDStream_usingDict(p->context, RSTRING_PTR(predict), RSTRING_LEN(predict));
261
392
  extzstd_check_error(s);
262
393
  }
394
+
395
+ p->inport = inport;
396
+ p->predict = predict;
397
+
263
398
  return self;
264
399
  }
265
400
 
401
+ static int
402
+ dec_read_fetch(VALUE o, struct decoder *p)
403
+ {
404
+ if (!p->inbuf.src || NIL_P(p->readbuf) || p->inbuf.pos >= RSTRING_LEN(p->readbuf)) {
405
+ p->readbuf = aux_str_buf_recycle(p->readbuf, EXT_PARTIAL_READ_SIZE);
406
+ VALUE st = AUX_FUNCALL(p->inport, id_read, INT2FIX(EXT_PARTIAL_READ_SIZE), p->readbuf);
407
+ if (NIL_P(st)) { return -1; }
408
+ rb_check_type(st, RUBY_T_STRING);
409
+ p->readbuf = st;
410
+ rb_obj_infect(o, p->readbuf);
411
+ p->inbuf.size = RSTRING_LEN(p->readbuf);
412
+ p->inbuf.pos = 0;
413
+ }
414
+
415
+ p->inbuf.src = RSTRING_PTR(p->readbuf);
416
+
417
+ return 0;
418
+ }
419
+
420
+ static size_t
421
+ dec_read_decode(VALUE o, struct decoder *p, char *buf, ssize_t size)
422
+ {
423
+ if (p->reached_eof != 0) {
424
+ return 0;
425
+ }
426
+
427
+ ZSTD_outBuffer output = { buf, size, 0 };
428
+
429
+ while (size < 0 || output.pos < size) {
430
+ if (dec_read_fetch(o, p) != 0) {
431
+ if (p->reached_eof == 0) {
432
+ rb_raise(rb_eRuntimeError,
433
+ "unexpected EOF - #<%s:%p>",
434
+ rb_obj_classname(p->inport), (void *)p->inport);
435
+ }
436
+
437
+ break;
438
+ }
439
+
440
+ rb_thread_check_ints();
441
+ size_t s = ZSTD_decompressStream(p->context, &output, &p->inbuf);
442
+ extzstd_check_error(s);
443
+ if (s == 0) {
444
+ p->reached_eof = 1;
445
+ break;
446
+ }
447
+ }
448
+
449
+ return output.pos;
450
+ }
451
+
452
+ static void
453
+ dec_read_args(int argc, VALUE argv[], VALUE self, VALUE *buf, ssize_t *size)
454
+ {
455
+ switch (argc) {
456
+ case 0:
457
+ *size = -1;
458
+ *buf = rb_str_buf_new(EXT_READ_GROWUP_SIZE);
459
+ break;
460
+ case 1:
461
+ case 2:
462
+ {
463
+ if (NIL_P(argv[0])) {
464
+ *size = -1;
465
+
466
+ if (argc == 1 || NIL_P(argv[1])) {
467
+ *buf = rb_str_buf_new(EXT_READ_GROWUP_SIZE);
468
+ } else {
469
+ rb_check_type(argv[1], RUBY_T_STRING);
470
+ *buf = aux_str_modify_expand(argv[1], EXT_READ_GROWUP_SIZE);
471
+ rb_str_set_len(*buf, 0);
472
+ }
473
+ } else {
474
+ *size = NUM2SIZET(argv[0]);
475
+
476
+ if (*size < 0) {
477
+ rb_raise(rb_eArgError,
478
+ "``size'' is negative or too large (%"PRIdPTR")",
479
+ (intptr_t)*size);
480
+ }
481
+
482
+ if (argc == 1 || NIL_P(argv[1])) {
483
+ *buf = rb_str_buf_new(*size);
484
+ } else {
485
+ rb_check_type(argv[1], RUBY_T_STRING);
486
+ *buf = aux_str_modify_expand(argv[1], *size);
487
+ rb_str_set_len(*buf, 0);
488
+ }
489
+ }
490
+ }
491
+ break;
492
+ default:
493
+ rb_error_arity(argc, 0, 2);
494
+ }
495
+ }
496
+
497
+ /*
498
+ * call-seq:
499
+ * read -> read_data
500
+ * read(readsize, buf = "".b) -> buf
501
+ */
266
502
  static VALUE
267
- dec_update(VALUE self, VALUE src, VALUE srcoff, VALUE dest, VALUE maxdest)
503
+ dec_read(int argc, VALUE argv[], VALUE self)
268
504
  {
269
505
  /*
270
506
  * ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
271
507
  */
272
508
 
273
- ZSTD_DStream *p = getdecoder(self);
509
+ ssize_t size;
510
+ VALUE buf;
511
+ dec_read_args(argc, argv, self, &buf, &size);
512
+
513
+ struct decoder *p = decoder_context(self);
274
514
 
275
- rb_check_type(src, RUBY_T_STRING);
276
- const char *q = RSTRING_PTR(src);
277
- const char *qq = RSTRING_END(src);
278
- const char *q1 = q + NUM2SIZET(srcoff);
279
- if (q1 < q || q1 > qq) {
280
- rb_raise(rb_eArgError,
281
- "``srcoff'' is out of range (given %"PRIuSIZE", expect 0..%"PRIuSIZE")",
282
- q1 - q, qq - q);
515
+ if (size == 0) {
516
+ rb_str_set_len(buf, 0);
517
+ return buf;
518
+ } else if (size > 0) {
519
+ size = dec_read_decode(self, p, RSTRING_PTR(buf), size);
520
+ rb_str_set_len(buf, size);
521
+ } else {
522
+ /* if (size < 0) */
523
+
524
+ size_t capa = EXT_READ_GROWUP_SIZE;
525
+
526
+ for (;;) {
527
+ aux_str_modify_expand(buf, capa);
528
+ size = dec_read_decode(self, p, RSTRING_PTR(buf) + RSTRING_LEN(buf), capa - RSTRING_LEN(buf));
529
+ rb_str_set_len(buf, RSTRING_LEN(buf) + size);
530
+ if (size == 0) { break; }
531
+ size = rb_str_capacity(buf);
532
+ if (size > RSTRING_LEN(buf)) { break; }
533
+ if (size > EXT_READ_DOUBLE_GROWUP_LIMIT_SIZE) {
534
+ capa += EXT_READ_DOUBLE_GROWUP_LIMIT_SIZE;
535
+ } else {
536
+ capa *= 2;
537
+ }
538
+ }
283
539
  }
284
540
 
285
- rb_check_type(dest, RUBY_T_STRING);
286
- rb_str_modify(dest);
287
- rb_str_set_len(dest, 0);
288
- rb_str_modify_expand(dest, NUM2SIZET(maxdest));
289
- rb_obj_infect(self, src);
290
- rb_obj_infect(dest, self);
291
- char *r = RSTRING_PTR(dest);
292
- const char *rr = r + rb_str_capacity(dest);
293
-
294
- ZSTD_inBuffer input = { q, qq - q, q1 - q };
295
- ZSTD_outBuffer output = { r, rr - r, 0 };
296
- size_t s = ZSTD_decompressStream(p, &output, &input);
297
- extzstd_check_error(s);
298
- rb_str_set_len(dest, output.pos);
299
- return SIZET2NUM(input.pos);
541
+ rb_obj_infect(buf, self);
542
+
543
+ if (RSTRING_LEN(buf) == 0) {
544
+ return Qnil;
545
+ } else {
546
+ return buf;
547
+ }
548
+ }
549
+
550
+ static VALUE
551
+ dec_eof(VALUE self)
552
+ {
553
+ return (decoder_context(self)->reached_eof == 0 ? Qfalse : Qtrue);
554
+ }
555
+
556
+ static VALUE
557
+ dec_close(VALUE self)
558
+ {
559
+ decoder_context(self)->reached_eof = 1;
560
+ return Qnil;
300
561
  }
301
562
 
302
563
  static VALUE
@@ -305,7 +566,7 @@ dec_reset(VALUE self)
305
566
  /*
306
567
  * ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
307
568
  */
308
- size_t s = ZSTD_resetDStream(getdecoder(self));
569
+ size_t s = ZSTD_resetDStream(decoder_context(self)->context);
309
570
  extzstd_check_error(s);
310
571
  return self;
311
572
  }
@@ -317,22 +578,33 @@ dec_sizeof(VALUE self)
317
578
  * ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
318
579
  */
319
580
 
320
- size_t s = ZSTD_sizeof_DStream(getdecoder(self));
581
+ size_t s = ZSTD_sizeof_DStream(decoder_context(self)->context);
321
582
  extzstd_check_error(s);
322
583
  return SIZET2NUM(s);
323
584
  }
324
585
 
586
+ static VALUE
587
+ dec_pos(VALUE self)
588
+ {
589
+ decoder_context(self); /* check only */
590
+ return INT2FIX(0);
591
+ }
592
+
325
593
  static void
326
594
  init_decoder(void)
327
595
  {
328
- cStreamDecoder = rb_define_class_under(extzstd_mZstd, "StreamDecoder", rb_cObject);
596
+ cStreamDecoder = rb_define_class_under(extzstd_mZstd, "Decoder", rb_cObject);
329
597
  rb_define_alloc_func(cStreamDecoder, dec_alloc);
330
598
  rb_define_const(cStreamDecoder, "INSIZE", SIZET2NUM(ZSTD_DStreamInSize()));
331
599
  rb_define_const(cStreamDecoder, "OUTSIZE", SIZET2NUM(ZSTD_DStreamOutSize()));
332
- rb_define_method(cStreamDecoder, "initialize", dec_init, 1);
333
- rb_define_method(cStreamDecoder, "update", dec_update, 4);
600
+ rb_define_method(cStreamDecoder, "initialize", dec_init, -1);
601
+ rb_define_method(cStreamDecoder, "read", dec_read, -1);
602
+ rb_define_method(cStreamDecoder, "eof", dec_eof, 0);
603
+ rb_define_alias(cStreamDecoder, "eof?", "eof");
604
+ rb_define_method(cStreamDecoder, "close", dec_close, 0);
334
605
  rb_define_method(cStreamDecoder, "reset", dec_reset, 0);
335
606
  rb_define_method(cStreamDecoder, "sizeof", dec_sizeof, 0);
607
+ rb_define_method(cStreamDecoder, "pos", dec_pos, 0);
336
608
  }
337
609
 
338
610
  /*
@@ -342,6 +614,9 @@ init_decoder(void)
342
614
  void
343
615
  extzstd_init_stream(void)
344
616
  {
617
+ id_op_lsh = rb_intern("<<");
618
+ id_read = rb_intern("read");
619
+
345
620
  init_encoder();
346
621
  init_decoder();
347
622
  }