zstd-ruby 1.5.6.6 → 2.0.1

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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/README.md +66 -1
  4. data/ext/zstdruby/common.h +38 -15
  5. data/ext/zstdruby/exports.txt +1 -0
  6. data/ext/zstdruby/extconf.rb +6 -1
  7. data/ext/zstdruby/libzstd/common/bits.h +92 -87
  8. data/ext/zstdruby/libzstd/common/bitstream.h +26 -29
  9. data/ext/zstdruby/libzstd/common/compiler.h +36 -22
  10. data/ext/zstdruby/libzstd/common/cpu.h +1 -1
  11. data/ext/zstdruby/libzstd/common/debug.h +0 -9
  12. data/ext/zstdruby/libzstd/common/error_private.c +1 -0
  13. data/ext/zstdruby/libzstd/common/error_private.h +0 -10
  14. data/ext/zstdruby/libzstd/common/fse.h +2 -17
  15. data/ext/zstdruby/libzstd/common/fse_decompress.c +2 -0
  16. data/ext/zstdruby/libzstd/common/huf.h +0 -9
  17. data/ext/zstdruby/libzstd/common/mem.h +7 -11
  18. data/ext/zstdruby/libzstd/common/pool.h +0 -9
  19. data/ext/zstdruby/libzstd/common/portability_macros.h +22 -9
  20. data/ext/zstdruby/libzstd/common/threading.h +0 -8
  21. data/ext/zstdruby/libzstd/common/xxhash.h +93 -19
  22. data/ext/zstdruby/libzstd/common/zstd_deps.h +12 -0
  23. data/ext/zstdruby/libzstd/common/zstd_internal.h +1 -69
  24. data/ext/zstdruby/libzstd/common/zstd_trace.h +5 -12
  25. data/ext/zstdruby/libzstd/compress/hist.c +10 -0
  26. data/ext/zstdruby/libzstd/compress/hist.h +7 -0
  27. data/ext/zstdruby/libzstd/compress/zstd_compress.c +1057 -367
  28. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +227 -125
  29. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +1 -1
  30. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +7 -7
  31. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +7 -6
  32. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +17 -17
  33. data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +41 -24
  34. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +58 -50
  35. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +4 -12
  36. data/ext/zstdruby/libzstd/compress/zstd_fast.c +91 -74
  37. data/ext/zstdruby/libzstd/compress/zstd_fast.h +4 -12
  38. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +64 -64
  39. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +30 -39
  40. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +48 -33
  41. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +6 -14
  42. data/ext/zstdruby/libzstd/compress/zstd_opt.c +55 -51
  43. data/ext/zstdruby/libzstd/compress/zstd_opt.h +8 -16
  44. data/ext/zstdruby/libzstd/compress/zstd_preSplit.c +238 -0
  45. data/ext/zstdruby/libzstd/compress/zstd_preSplit.h +33 -0
  46. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +134 -93
  47. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +4 -15
  48. data/ext/zstdruby/libzstd/decompress/huf_decompress_amd64.S +10 -3
  49. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +14 -11
  50. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +6 -12
  51. data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +5 -5
  52. data/ext/zstdruby/libzstd/dictBuilder/cover.c +60 -19
  53. data/ext/zstdruby/libzstd/dictBuilder/divsufsort.h +0 -10
  54. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +2 -2
  55. data/ext/zstdruby/libzstd/zdict.h +15 -8
  56. data/ext/zstdruby/libzstd/zstd.h +241 -132
  57. data/ext/zstdruby/libzstd/zstd_errors.h +1 -8
  58. data/ext/zstdruby/main.c +5 -1
  59. data/ext/zstdruby/streaming_compress.c +28 -13
  60. data/ext/zstdruby/streaming_decompress.c +31 -2
  61. data/ext/zstdruby/zstdruby.c +146 -125
  62. data/lib/zstd-ruby/stream_writer.rb +1 -1
  63. data/lib/zstd-ruby/version.rb +1 -1
  64. metadata +6 -6
@@ -15,10 +15,6 @@
15
15
  extern "C" {
16
16
  #endif
17
17
 
18
- /*===== dependency =====*/
19
- #include <stddef.h> /* size_t */
20
-
21
-
22
18
  /* ===== ZSTDERRORLIB_API : control library symbols visibility ===== */
23
19
  #ifndef ZSTDERRORLIB_VISIBLE
24
20
  /* Backwards compatibility with old macro name */
@@ -80,6 +76,7 @@ typedef enum {
80
76
  ZSTD_error_tableLog_tooLarge = 44,
81
77
  ZSTD_error_maxSymbolValue_tooLarge = 46,
82
78
  ZSTD_error_maxSymbolValue_tooSmall = 48,
79
+ ZSTD_error_cannotProduce_uncompressedBlock = 49,
83
80
  ZSTD_error_stabilityCondition_notRespected = 50,
84
81
  ZSTD_error_stage_wrong = 60,
85
82
  ZSTD_error_init_missing = 62,
@@ -100,10 +97,6 @@ typedef enum {
100
97
  ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */
101
98
  } ZSTD_ErrorCode;
102
99
 
103
- /*! ZSTD_getErrorCode() :
104
- convert a `size_t` function result into a `ZSTD_ErrorCode` enum type,
105
- which can be used to compare with enum list published above */
106
- ZSTDERRORLIB_API ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult);
107
100
  ZSTDERRORLIB_API const char* ZSTD_getErrorString(ZSTD_ErrorCode code); /**< Same as ZSTD_getErrorName, but using a `ZSTD_ErrorCode` enum argument */
108
101
 
109
102
 
data/ext/zstdruby/main.c CHANGED
@@ -1,12 +1,14 @@
1
1
  #include "common.h"
2
2
 
3
3
  VALUE rb_mZstd;
4
+ VALUE rb_cCDict;
5
+ VALUE rb_cDDict;
4
6
  void zstd_ruby_init(void);
5
7
  void zstd_ruby_skippable_frame_init(void);
6
8
  void zstd_ruby_streaming_compress_init(void);
7
9
  void zstd_ruby_streaming_decompress_init(void);
8
10
 
9
- void
11
+ RUBY_FUNC_EXPORTED void
10
12
  Init_zstdruby(void)
11
13
  {
12
14
  #ifdef HAVE_RB_EXT_RACTOR_SAFE
@@ -14,6 +16,8 @@ Init_zstdruby(void)
14
16
  #endif
15
17
 
16
18
  rb_mZstd = rb_define_module("Zstd");
19
+ rb_cCDict = rb_define_class_under(rb_mZstd, "CDict", rb_cObject);
20
+ rb_cDDict = rb_define_class_under(rb_mZstd, "DDict", rb_cObject);
17
21
  zstd_ruby_init();
18
22
  zstd_ruby_skippable_frame_init();
19
23
  zstd_ruby_streaming_compress_init();
@@ -4,6 +4,7 @@ struct streaming_compress_t {
4
4
  ZSTD_CCtx* ctx;
5
5
  VALUE buf;
6
6
  size_t buf_size;
7
+ VALUE pending; /* accumulate compressed bytes produced by write() */
7
8
  };
8
9
 
9
10
  static void
@@ -12,8 +13,10 @@ streaming_compress_mark(void *p)
12
13
  struct streaming_compress_t *sc = p;
13
14
  #ifdef HAVE_RB_GC_MARK_MOVABLE
14
15
  rb_gc_mark_movable(sc->buf);
16
+ rb_gc_mark_movable(sc->pending);
15
17
  #else
16
18
  rb_gc_mark(sc->buf);
19
+ rb_gc_mark(sc->pending);
17
20
  #endif
18
21
  }
19
22
 
@@ -40,6 +43,7 @@ streaming_compress_compact(void *p)
40
43
  {
41
44
  struct streaming_compress_t *sc = p;
42
45
  sc->buf = rb_gc_location(sc->buf);
46
+ sc->pending = rb_gc_location(sc->pending);
43
47
  }
44
48
  #endif
45
49
 
@@ -64,6 +68,7 @@ rb_streaming_compress_allocate(VALUE klass)
64
68
  sc->ctx = NULL;
65
69
  sc->buf = Qnil;
66
70
  sc->buf_size = 0;
71
+ sc->pending = Qnil;
67
72
  return obj;
68
73
  }
69
74
 
@@ -71,8 +76,7 @@ static VALUE
71
76
  rb_streaming_compress_initialize(int argc, VALUE *argv, VALUE obj)
72
77
  {
73
78
  VALUE kwargs;
74
- VALUE compression_level_value;
75
- rb_scan_args(argc, argv, "01:", &compression_level_value, &kwargs);
79
+ rb_scan_args(argc, argv, "00:", &kwargs);
76
80
 
77
81
  struct streaming_compress_t* sc;
78
82
  TypedData_Get_Struct(obj, struct streaming_compress_t, &streaming_compress_type, sc);
@@ -82,11 +86,12 @@ rb_streaming_compress_initialize(int argc, VALUE *argv, VALUE obj)
82
86
  if (ctx == NULL) {
83
87
  rb_raise(rb_eRuntimeError, "%s", "ZSTD_createCCtx error");
84
88
  }
85
- set_compress_params(ctx, compression_level_value, kwargs);
89
+ set_compress_params(ctx, kwargs);
86
90
 
87
91
  sc->ctx = ctx;
88
92
  sc->buf = rb_str_new(NULL, buffOutSize);
89
93
  sc->buf_size = buffOutSize;
94
+ sc->pending = rb_str_new(0, 0);
90
95
 
91
96
  return obj;
92
97
  }
@@ -100,13 +105,13 @@ static VALUE
100
105
  no_compress(struct streaming_compress_t* sc, ZSTD_EndDirective endOp)
101
106
  {
102
107
  ZSTD_inBuffer input = { NULL, 0, 0 };
103
- const char* output_data = RSTRING_PTR(sc->buf);
104
108
  VALUE result = rb_str_new(0, 0);
105
109
  size_t ret;
106
110
  do {
111
+ const char* output_data = RSTRING_PTR(sc->buf);
107
112
  ZSTD_outBuffer output = { (void*)output_data, sc->buf_size, 0 };
108
113
 
109
- size_t const ret = zstd_stream_compress(sc->ctx, &output, &input, endOp, false);
114
+ ret = zstd_stream_compress(sc->ctx, &output, &input, endOp, false);
110
115
  if (ZSTD_isError(ret)) {
111
116
  rb_raise(rb_eRuntimeError, "flush error error code: %s", ZSTD_getErrorName(ret));
112
117
  }
@@ -126,9 +131,9 @@ rb_streaming_compress_compress(VALUE obj, VALUE src)
126
131
  struct streaming_compress_t* sc;
127
132
  TypedData_Get_Struct(obj, struct streaming_compress_t, &streaming_compress_type, sc);
128
133
 
129
- const char* output_data = RSTRING_PTR(sc->buf);
130
134
  VALUE result = rb_str_new(0, 0);
131
135
  while (input.pos < input.size) {
136
+ const char* output_data = RSTRING_PTR(sc->buf);
132
137
  ZSTD_outBuffer output = { (void*)output_data, sc->buf_size, 0 };
133
138
  size_t const ret = zstd_stream_compress(sc->ctx, &output, &input, ZSTD_e_continue, false);
134
139
  if (ZSTD_isError(ret)) {
@@ -143,10 +148,8 @@ static VALUE
143
148
  rb_streaming_compress_write(int argc, VALUE *argv, VALUE obj)
144
149
  {
145
150
  size_t total = 0;
146
- VALUE result = rb_str_new(0, 0);
147
151
  struct streaming_compress_t* sc;
148
152
  TypedData_Get_Struct(obj, struct streaming_compress_t, &streaming_compress_type, sc);
149
- const char* output_data = RSTRING_PTR(sc->buf);
150
153
 
151
154
  while (argc-- > 0) {
152
155
  VALUE str = *argv++;
@@ -156,14 +159,20 @@ rb_streaming_compress_write(int argc, VALUE *argv, VALUE obj)
156
159
  ZSTD_inBuffer input = { input_data, input_size, 0 };
157
160
 
158
161
  while (input.pos < input.size) {
162
+ const char* output_data = RSTRING_PTR(sc->buf);
159
163
  ZSTD_outBuffer output = { (void*)output_data, sc->buf_size, 0 };
160
164
  size_t const ret = zstd_stream_compress(sc->ctx, &output, &input, ZSTD_e_continue, false);
161
165
  if (ZSTD_isError(ret)) {
162
166
  rb_raise(rb_eRuntimeError, "compress error error code: %s", ZSTD_getErrorName(ret));
163
167
  }
164
- total += RSTRING_LEN(str);
168
+ /* Directly append to the pending buffer */
169
+ if (output.pos > 0) {
170
+ rb_str_cat(sc->pending, output.dst, output.pos);
171
+ }
165
172
  }
173
+ total += RSTRING_LEN(str);
166
174
  }
175
+
167
176
  return SIZET2NUM(total);
168
177
  }
169
178
 
@@ -193,8 +202,11 @@ rb_streaming_compress_flush(VALUE obj)
193
202
  {
194
203
  struct streaming_compress_t* sc;
195
204
  TypedData_Get_Struct(obj, struct streaming_compress_t, &streaming_compress_type, sc);
196
- VALUE result = no_compress(sc, ZSTD_e_flush);
197
- return result;
205
+ VALUE drained = no_compress(sc, ZSTD_e_flush);
206
+ VALUE out = rb_str_dup(sc->pending);
207
+ rb_str_cat(out, RSTRING_PTR(drained), RSTRING_LEN(drained));
208
+ rb_str_resize(sc->pending, 0);
209
+ return out;
198
210
  }
199
211
 
200
212
  static VALUE
@@ -202,8 +214,11 @@ rb_streaming_compress_finish(VALUE obj)
202
214
  {
203
215
  struct streaming_compress_t* sc;
204
216
  TypedData_Get_Struct(obj, struct streaming_compress_t, &streaming_compress_type, sc);
205
- VALUE result = no_compress(sc, ZSTD_e_end);
206
- return result;
217
+ VALUE drained = no_compress(sc, ZSTD_e_end);
218
+ VALUE out = rb_str_dup(sc->pending);
219
+ rb_str_cat(out, RSTRING_PTR(drained), RSTRING_LEN(drained));
220
+ rb_str_resize(sc->pending, 0);
221
+ return out;
207
222
  }
208
223
 
209
224
  extern VALUE rb_mZstd, cStreamingCompress;
@@ -100,19 +100,47 @@ rb_streaming_decompress_decompress(VALUE obj, VALUE src)
100
100
 
101
101
  struct streaming_decompress_t* sd;
102
102
  TypedData_Get_Struct(obj, struct streaming_decompress_t, &streaming_decompress_type, sd);
103
- const char* output_data = RSTRING_PTR(sd->buf);
104
103
  VALUE result = rb_str_new(0, 0);
104
+
105
105
  while (input.pos < input.size) {
106
+ const char* output_data = RSTRING_PTR(sd->buf);
106
107
  ZSTD_outBuffer output = { (void*)output_data, sd->buf_size, 0 };
107
108
  size_t const ret = zstd_stream_decompress(sd->dctx, &output, &input, false);
109
+
108
110
  if (ZSTD_isError(ret)) {
109
111
  rb_raise(rb_eRuntimeError, "decompress error error code: %s", ZSTD_getErrorName(ret));
110
112
  }
111
- rb_str_cat(result, output.dst, output.pos);
113
+ if (output.pos > 0) {
114
+ rb_str_cat(result, output.dst, output.pos);
115
+ }
116
+ if (ret == 0 && output.pos == 0) {
117
+ break;
118
+ }
112
119
  }
113
120
  return result;
114
121
  }
115
122
 
123
+ static VALUE
124
+ rb_streaming_decompress_decompress_with_pos(VALUE obj, VALUE src)
125
+ {
126
+ StringValue(src);
127
+ const char* input_data = RSTRING_PTR(src);
128
+ size_t input_size = RSTRING_LEN(src);
129
+ ZSTD_inBuffer input = { input_data, input_size, 0 };
130
+
131
+ struct streaming_decompress_t* sd;
132
+ TypedData_Get_Struct(obj, struct streaming_decompress_t, &streaming_decompress_type, sd);
133
+ const char* output_data = RSTRING_PTR(sd->buf);
134
+ VALUE result = rb_str_new(0, 0);
135
+ ZSTD_outBuffer output = { (void*)output_data, sd->buf_size, 0 };
136
+ size_t const ret = zstd_stream_decompress(sd->dctx, &output, &input, false);
137
+ if (ZSTD_isError(ret)) {
138
+ rb_raise(rb_eRuntimeError, "decompress error error code: %s", ZSTD_getErrorName(ret));
139
+ }
140
+ rb_str_cat(result, output.dst, output.pos);
141
+ return rb_ary_new_from_args(2, result, ULONG2NUM(input.pos));
142
+ }
143
+
116
144
  extern VALUE rb_mZstd, cStreamingDecompress;
117
145
  void
118
146
  zstd_ruby_streaming_decompress_init(void)
@@ -121,4 +149,5 @@ zstd_ruby_streaming_decompress_init(void)
121
149
  rb_define_alloc_func(cStreamingDecompress, rb_streaming_decompress_allocate);
122
150
  rb_define_method(cStreamingDecompress, "initialize", rb_streaming_decompress_initialize, -1);
123
151
  rb_define_method(cStreamingDecompress, "decompress", rb_streaming_decompress_decompress, 1);
152
+ rb_define_method(cStreamingDecompress, "decompress_with_pos", rb_streaming_decompress_decompress_with_pos, 1);
124
153
  }
@@ -11,16 +11,15 @@ static VALUE zstdVersion(VALUE self)
11
11
  static VALUE rb_compress(int argc, VALUE *argv, VALUE self)
12
12
  {
13
13
  VALUE input_value;
14
- VALUE compression_level_value;
15
14
  VALUE kwargs;
16
- rb_scan_args(argc, argv, "11:", &input_value, &compression_level_value, &kwargs);
15
+ rb_scan_args(argc, argv, "10:", &input_value, &kwargs);
17
16
 
18
17
  ZSTD_CCtx* const ctx = ZSTD_createCCtx();
19
18
  if (ctx == NULL) {
20
19
  rb_raise(rb_eRuntimeError, "%s", "ZSTD_createCCtx error");
21
20
  }
22
21
 
23
- set_compress_params(ctx, compression_level_value, kwargs);
22
+ set_compress_params(ctx, kwargs);
24
23
 
25
24
  StringValue(input_value);
26
25
  char* input_data = RSTRING_PTR(input_value);
@@ -40,159 +39,175 @@ static VALUE rb_compress(int argc, VALUE *argv, VALUE self)
40
39
  return output;
41
40
  }
42
41
 
43
- static VALUE rb_compress_using_dict(int argc, VALUE *argv, VALUE self)
44
- {
45
- rb_warn("Zstd.compress_using_dict is deprecated; use Zstd.compress with `dict:` instead.");
46
- VALUE input_value;
47
- VALUE dict;
48
- VALUE compression_level_value;
49
- rb_scan_args(argc, argv, "21", &input_value, &dict, &compression_level_value);
50
- int compression_level = convert_compression_level(compression_level_value);
42
+ static VALUE decode_one_frame(ZSTD_DCtx* dctx, const unsigned char* src, size_t size, VALUE kwargs) {
43
+ VALUE out = rb_str_buf_new(0);
44
+ size_t cap = ZSTD_DStreamOutSize();
45
+ char *buf = ALLOC_N(char, cap);
46
+ ZSTD_inBuffer in = (ZSTD_inBuffer){ src, size, 0 };
51
47
 
48
+ ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only);
49
+ set_decompress_params(dctx, kwargs);
50
+
51
+ for (;;) {
52
+ ZSTD_outBuffer o = (ZSTD_outBuffer){ buf, cap, 0 };
53
+ size_t ret = ZSTD_decompressStream(dctx, &o, &in);
54
+ if (ZSTD_isError(ret)) {
55
+ xfree(buf);
56
+ rb_raise(rb_eRuntimeError, "ZSTD_decompressStream failed: %s", ZSTD_getErrorName(ret));
57
+ }
58
+ if (o.pos) {
59
+ rb_str_cat(out, buf, o.pos);
60
+ }
61
+ if (ret == 0) {
62
+ break;
63
+ }
64
+ }
65
+ xfree(buf);
66
+ return out;
67
+ }
68
+
69
+ static VALUE decompress_buffered(ZSTD_DCtx* dctx, const char* data, size_t len) {
70
+ return decode_one_frame(dctx, (const unsigned char*)data, len, Qnil);
71
+ }
72
+
73
+ static VALUE rb_decompress(int argc, VALUE *argv, VALUE self)
74
+ {
75
+ VALUE input_value, kwargs;
76
+ rb_scan_args(argc, argv, "10:", &input_value, &kwargs);
52
77
  StringValue(input_value);
53
- char* input_data = RSTRING_PTR(input_value);
54
- size_t input_size = RSTRING_LEN(input_value);
55
- size_t max_compressed_size = ZSTD_compressBound(input_size);
56
78
 
57
- char* dict_buffer = RSTRING_PTR(dict);
58
- size_t dict_size = RSTRING_LEN(dict);
79
+ size_t in_size = RSTRING_LEN(input_value);
80
+ const unsigned char *in_r = (const unsigned char *)RSTRING_PTR(input_value);
81
+ unsigned char *in = ALLOC_N(unsigned char, in_size);
82
+ memcpy(in, in_r, in_size);
83
+
84
+ size_t off = 0;
85
+ const uint32_t ZSTD_MAGIC = 0xFD2FB528U;
86
+ const uint32_t SKIP_LO = 0x184D2A50U; /* ...5F */
87
+
88
+ while (off + 4 <= in_size) {
89
+ uint32_t magic = (uint32_t)in[off]
90
+ | ((uint32_t)in[off+1] << 8)
91
+ | ((uint32_t)in[off+2] << 16)
92
+ | ((uint32_t)in[off+3] << 24);
93
+
94
+ if ((magic & 0xFFFFFFF0U) == (SKIP_LO & 0xFFFFFFF0U)) {
95
+ if (off + 8 > in_size) break;
96
+ uint32_t skipLen = (uint32_t)in[off+4]
97
+ | ((uint32_t)in[off+5] << 8)
98
+ | ((uint32_t)in[off+6] << 16)
99
+ | ((uint32_t)in[off+7] << 24);
100
+ size_t adv = (size_t)8 + (size_t)skipLen;
101
+ if (off + adv > in_size) break;
102
+ off += adv;
103
+ continue;
104
+ }
59
105
 
60
- ZSTD_CDict* const cdict = ZSTD_createCDict(dict_buffer, dict_size, compression_level);
61
- if (cdict == NULL) {
62
- rb_raise(rb_eRuntimeError, "%s", "ZSTD_createCDict failed");
63
- }
64
- ZSTD_CCtx* const ctx = ZSTD_createCCtx();
65
- if (ctx == NULL) {
66
- ZSTD_freeCDict(cdict);
67
- rb_raise(rb_eRuntimeError, "%s", "ZSTD_createCCtx failed");
68
- }
106
+ if (magic == ZSTD_MAGIC) {
107
+ ZSTD_DCtx *dctx = ZSTD_createDCtx();
108
+ if (!dctx) {
109
+ xfree(in);
110
+ rb_raise(rb_eRuntimeError, "ZSTD_createDCtx failed");
111
+ }
69
112
 
70
- VALUE output = rb_str_new(NULL, max_compressed_size);
71
- char* output_data = RSTRING_PTR(output);
72
- size_t const compressed_size = ZSTD_compress_usingCDict(ctx, (void*)output_data, max_compressed_size,
73
- (void*)input_data, input_size, cdict);
113
+ VALUE out = decode_one_frame(dctx, in + off, in_size - off, kwargs);
74
114
 
75
- if (ZSTD_isError(compressed_size)) {
76
- ZSTD_freeCDict(cdict);
77
- ZSTD_freeCCtx(ctx);
78
- rb_raise(rb_eRuntimeError, "%s: %s", "compress failed", ZSTD_getErrorName(compressed_size));
115
+ ZSTD_freeDCtx(dctx);
116
+ xfree(in);
117
+ RB_GC_GUARD(input_value);
118
+ return out;
119
+ }
120
+
121
+ off += 1;
79
122
  }
80
123
 
81
- rb_str_resize(output, compressed_size);
82
- ZSTD_freeCDict(cdict);
83
- ZSTD_freeCCtx(ctx);
84
- return output;
124
+ xfree(in);
125
+ RB_GC_GUARD(input_value);
126
+ rb_raise(rb_eRuntimeError, "not a zstd frame (magic not found)");
85
127
  }
86
128
 
87
-
88
- static VALUE decompress_buffered(ZSTD_DCtx* dctx, const char* input_data, size_t input_size)
129
+ static void free_cdict(void *dict)
89
130
  {
90
- ZSTD_inBuffer input = { input_data, input_size, 0 };
91
- VALUE result = rb_str_new(0, 0);
131
+ ZSTD_freeCDict(dict);
132
+ }
92
133
 
93
- while (input.pos < input.size) {
94
- ZSTD_outBuffer output = { NULL, 0, 0 };
95
- output.size += ZSTD_DStreamOutSize();
96
- VALUE output_string = rb_str_new(NULL, output.size);
97
- output.dst = RSTRING_PTR(output_string);
134
+ static size_t sizeof_cdict(const void *dict)
135
+ {
136
+ return ZSTD_sizeof_CDict(dict);
137
+ }
98
138
 
99
- size_t ret = zstd_stream_decompress(dctx, &output, &input, false);
100
- if (ZSTD_isError(ret)) {
101
- ZSTD_freeDCtx(dctx);
102
- rb_raise(rb_eRuntimeError, "%s: %s", "ZSTD_decompressStream failed", ZSTD_getErrorName(ret));
103
- }
104
- rb_str_cat(result, output.dst, output.pos);
105
- }
106
- ZSTD_freeDCtx(dctx);
107
- return result;
139
+ static void free_ddict(void *dict)
140
+ {
141
+ ZSTD_freeDDict(dict);
108
142
  }
109
143
 
110
- static VALUE rb_decompress(int argc, VALUE *argv, VALUE self)
144
+ static size_t sizeof_ddict(const void *dict)
111
145
  {
112
- VALUE input_value;
113
- VALUE kwargs;
114
- rb_scan_args(argc, argv, "10:", &input_value, &kwargs);
115
- StringValue(input_value);
116
- char* input_data = RSTRING_PTR(input_value);
117
- size_t input_size = RSTRING_LEN(input_value);
118
- ZSTD_DCtx* const dctx = ZSTD_createDCtx();
119
- if (dctx == NULL) {
120
- rb_raise(rb_eRuntimeError, "%s", "ZSTD_createDCtx failed");
121
- }
122
- set_decompress_params(dctx, kwargs);
146
+ return ZSTD_sizeof_DDict(dict);
147
+ }
123
148
 
124
- unsigned long long const uncompressed_size = ZSTD_getFrameContentSize(input_data, input_size);
125
- if (uncompressed_size == ZSTD_CONTENTSIZE_ERROR) {
126
- rb_raise(rb_eRuntimeError, "%s: %s", "not compressed by zstd", ZSTD_getErrorName(uncompressed_size));
127
- }
128
- // ZSTD_decompressStream may be called multiple times when ZSTD_CONTENTSIZE_UNKNOWN, causing slowness.
129
- // Therefore, we will not standardize on ZSTD_decompressStream
130
- if (uncompressed_size == ZSTD_CONTENTSIZE_UNKNOWN) {
131
- return decompress_buffered(dctx, input_data, input_size);
132
- }
149
+ static const rb_data_type_t cdict_type = {
150
+ "Zstd::CDict",
151
+ {0, free_cdict, sizeof_cdict,},
152
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
153
+ };
133
154
 
134
- VALUE output = rb_str_new(NULL, uncompressed_size);
135
- char* output_data = RSTRING_PTR(output);
155
+ static const rb_data_type_t ddict_type = {
156
+ "Zstd::DDict",
157
+ {0, free_ddict, sizeof_ddict,},
158
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
159
+ };
136
160
 
137
- size_t const decompress_size = zstd_decompress(dctx, output_data, uncompressed_size, input_data, input_size, false);
138
- if (ZSTD_isError(decompress_size)) {
139
- rb_raise(rb_eRuntimeError, "%s: %s", "decompress error", ZSTD_getErrorName(decompress_size));
140
- }
141
- ZSTD_freeDCtx(dctx);
142
- return output;
161
+ static VALUE rb_cdict_alloc(VALUE self)
162
+ {
163
+ ZSTD_CDict* cdict = NULL;
164
+ return TypedData_Wrap_Struct(self, &cdict_type, cdict);
143
165
  }
144
166
 
145
- static VALUE rb_decompress_using_dict(int argc, VALUE *argv, VALUE self)
167
+ static VALUE rb_cdict_initialize(int argc, VALUE *argv, VALUE self)
146
168
  {
147
- rb_warn("Zstd.decompress_using_dict is deprecated; use Zstd.decompress with `dict:` instead.");
148
- VALUE input_value;
149
169
  VALUE dict;
150
- rb_scan_args(argc, argv, "20", &input_value, &dict);
170
+ VALUE compression_level_value;
171
+ rb_scan_args(argc, argv, "11", &dict, &compression_level_value);
172
+ int compression_level = convert_compression_level(compression_level_value);
151
173
 
152
- StringValue(input_value);
153
- char* input_data = RSTRING_PTR(input_value);
154
- size_t input_size = RSTRING_LEN(input_value);
174
+ StringValue(dict);
175
+ char* dict_buffer = RSTRING_PTR(dict);
176
+ size_t dict_size = RSTRING_LEN(dict);
155
177
 
178
+ ZSTD_CDict* const cdict = ZSTD_createCDict(dict_buffer, dict_size, compression_level);
179
+ if (cdict == NULL) {
180
+ rb_raise(rb_eRuntimeError, "%s", "ZSTD_createCDict failed");
181
+ }
182
+
183
+ DATA_PTR(self) = cdict;
184
+ return self;
185
+ }
186
+
187
+ static VALUE rb_ddict_alloc(VALUE self)
188
+ {
189
+ ZSTD_CDict* ddict = NULL;
190
+ return TypedData_Wrap_Struct(self, &ddict_type, ddict);
191
+ }
192
+
193
+ static VALUE rb_ddict_initialize(VALUE self, VALUE dict)
194
+ {
195
+ StringValue(dict);
156
196
  char* dict_buffer = RSTRING_PTR(dict);
157
197
  size_t dict_size = RSTRING_LEN(dict);
198
+
158
199
  ZSTD_DDict* const ddict = ZSTD_createDDict(dict_buffer, dict_size);
159
200
  if (ddict == NULL) {
160
201
  rb_raise(rb_eRuntimeError, "%s", "ZSTD_createDDict failed");
161
202
  }
162
- unsigned const expected_dict_id = ZSTD_getDictID_fromDDict(ddict);
163
- unsigned const actual_dict_id = ZSTD_getDictID_fromFrame(input_data, input_size);
164
- if (expected_dict_id != actual_dict_id) {
165
- ZSTD_freeDDict(ddict);
166
- rb_raise(rb_eRuntimeError, "DictID mismatch");
167
- }
168
203
 
169
- ZSTD_DCtx* const ctx = ZSTD_createDCtx();
170
- if (ctx == NULL) {
171
- ZSTD_freeDDict(ddict);
172
- rb_raise(rb_eRuntimeError, "%s", "ZSTD_createDCtx failed");
173
- }
174
-
175
- unsigned long long const uncompressed_size = ZSTD_getFrameContentSize(input_data, input_size);
176
- if (uncompressed_size == ZSTD_CONTENTSIZE_ERROR) {
177
- ZSTD_freeDDict(ddict);
178
- ZSTD_freeDCtx(ctx);
179
- rb_raise(rb_eRuntimeError, "%s: %s", "not compressed by zstd", ZSTD_getErrorName(uncompressed_size));
180
- }
181
- if (uncompressed_size == ZSTD_CONTENTSIZE_UNKNOWN) {
182
- return decompress_buffered(ctx, input_data, input_size);
183
- }
204
+ DATA_PTR(self) = ddict;
205
+ return self;
206
+ }
184
207
 
185
- VALUE output = rb_str_new(NULL, uncompressed_size);
186
- char* output_data = RSTRING_PTR(output);
187
- size_t const decompress_size = ZSTD_decompress_usingDDict(ctx, output_data, uncompressed_size, input_data, input_size, ddict);
188
- if (ZSTD_isError(decompress_size)) {
189
- ZSTD_freeDDict(ddict);
190
- ZSTD_freeDCtx(ctx);
191
- rb_raise(rb_eRuntimeError, "%s: %s", "decompress error", ZSTD_getErrorName(decompress_size));
192
- }
193
- ZSTD_freeDDict(ddict);
194
- ZSTD_freeDCtx(ctx);
195
- return output;
208
+ static VALUE rb_prohibit_copy(VALUE self, VALUE obj)
209
+ {
210
+ rb_raise(rb_eRuntimeError, "CDict cannot be duplicated");
196
211
  }
197
212
 
198
213
  void
@@ -200,7 +215,13 @@ zstd_ruby_init(void)
200
215
  {
201
216
  rb_define_module_function(rb_mZstd, "zstd_version", zstdVersion, 0);
202
217
  rb_define_module_function(rb_mZstd, "compress", rb_compress, -1);
203
- rb_define_module_function(rb_mZstd, "compress_using_dict", rb_compress_using_dict, -1);
204
218
  rb_define_module_function(rb_mZstd, "decompress", rb_decompress, -1);
205
- rb_define_module_function(rb_mZstd, "decompress_using_dict", rb_decompress_using_dict, -1);
219
+
220
+ rb_define_alloc_func(rb_cCDict, rb_cdict_alloc);
221
+ rb_define_private_method(rb_cCDict, "initialize", rb_cdict_initialize, -1);
222
+ rb_define_method(rb_cCDict, "initialize_copy", rb_prohibit_copy, 1);
223
+
224
+ rb_define_alloc_func(rb_cDDict, rb_ddict_alloc);
225
+ rb_define_private_method(rb_cDDict, "initialize", rb_ddict_initialize, 1);
226
+ rb_define_method(rb_cDDict, "initialize_copy", rb_prohibit_copy, 1);
206
227
  }
@@ -3,7 +3,7 @@ module Zstd
3
3
  class StreamWriter
4
4
  def initialize(io, level: nil)
5
5
  @io = io
6
- @stream = Zstd::StreamingCompress.new(level)
6
+ @stream = Zstd::StreamingCompress.new(level: level)
7
7
  end
8
8
 
9
9
  def write(*data)
@@ -1,3 +1,3 @@
1
1
  module Zstd
2
- VERSION = "1.5.6.6"
2
+ VERSION = "2.0.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zstd-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.6.6
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - SpringMT
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-05-23 00:00:00.000000000 Z
10
+ date: 2025-09-29 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: bundler
@@ -100,6 +99,7 @@ files:
100
99
  - bin/console
101
100
  - bin/setup
102
101
  - ext/zstdruby/common.h
102
+ - ext/zstdruby/exports.txt
103
103
  - ext/zstdruby/extconf.rb
104
104
  - ext/zstdruby/libzstd/common/allocations.h
105
105
  - ext/zstdruby/libzstd/common/bits.h
@@ -151,6 +151,8 @@ files:
151
151
  - ext/zstdruby/libzstd/compress/zstd_ldm_geartab.h
152
152
  - ext/zstdruby/libzstd/compress/zstd_opt.c
153
153
  - ext/zstdruby/libzstd/compress/zstd_opt.h
154
+ - ext/zstdruby/libzstd/compress/zstd_preSplit.c
155
+ - ext/zstdruby/libzstd/compress/zstd_preSplit.h
154
156
  - ext/zstdruby/libzstd/compress/zstdmt_compress.c
155
157
  - ext/zstdruby/libzstd/compress/zstdmt_compress.h
156
158
  - ext/zstdruby/libzstd/decompress/huf_decompress.c
@@ -185,7 +187,6 @@ homepage: https://github.com/SpringMT/zstd-ruby
185
187
  licenses:
186
188
  - MIT
187
189
  metadata: {}
188
- post_install_message:
189
190
  rdoc_options: []
190
191
  require_paths:
191
192
  - lib
@@ -200,8 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
200
201
  - !ruby/object:Gem::Version
201
202
  version: '0'
202
203
  requirements: []
203
- rubygems_version: 3.5.3
204
- signing_key:
204
+ rubygems_version: 3.6.2
205
205
  specification_version: 4
206
206
  summary: Ruby binding for zstd(Zstandard - Fast real-time compression algorithm)
207
207
  test_files: []