zstd-ruby 2.0.0.pre.preview1 → 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.
- checksums.yaml +4 -4
- data/ext/zstdruby/streaming_compress.c +26 -10
- data/ext/zstdruby/streaming_decompress.c +9 -2
- data/ext/zstdruby/zstdruby.c +70 -40
- data/lib/zstd-ruby/version.rb +1 -1
- metadata +5 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91a2e54ff93b0c602d6b2d064f6f8c615a59f0ef963c20b24e4db6d17643163e
|
4
|
+
data.tar.gz: cbeb4c7c21187336a284cb714765fb80b02b982c6b4fafa60784d8f7950fe528
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 70190b1a1233782dc440e5ef913f4a83b6bc936ea96d744f5a44b3dbceb41f8a1ef9c3264746eb251356b95c13c5503b2b2567076bc45c28d628ee278b9c2522
|
7
|
+
data.tar.gz: 600bc166bef41126b93a0e78190bbf6b5698259797e166ee4d787a113d6c4e27e7c6c927135e54b33a7e4cc25a74b2df4cb19413f74618892191863cc4c9b4fb
|
@@ -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
|
|
@@ -86,6 +91,7 @@ rb_streaming_compress_initialize(int argc, VALUE *argv, VALUE obj)
|
|
86
91
|
sc->ctx = ctx;
|
87
92
|
sc->buf = rb_str_new(NULL, buffOutSize);
|
88
93
|
sc->buf_size = buffOutSize;
|
94
|
+
sc->pending = rb_str_new(0, 0);
|
89
95
|
|
90
96
|
return obj;
|
91
97
|
}
|
@@ -99,13 +105,13 @@ static VALUE
|
|
99
105
|
no_compress(struct streaming_compress_t* sc, ZSTD_EndDirective endOp)
|
100
106
|
{
|
101
107
|
ZSTD_inBuffer input = { NULL, 0, 0 };
|
102
|
-
const char* output_data = RSTRING_PTR(sc->buf);
|
103
108
|
VALUE result = rb_str_new(0, 0);
|
104
109
|
size_t ret;
|
105
110
|
do {
|
111
|
+
const char* output_data = RSTRING_PTR(sc->buf);
|
106
112
|
ZSTD_outBuffer output = { (void*)output_data, sc->buf_size, 0 };
|
107
113
|
|
108
|
-
|
114
|
+
ret = zstd_stream_compress(sc->ctx, &output, &input, endOp, false);
|
109
115
|
if (ZSTD_isError(ret)) {
|
110
116
|
rb_raise(rb_eRuntimeError, "flush error error code: %s", ZSTD_getErrorName(ret));
|
111
117
|
}
|
@@ -125,9 +131,9 @@ rb_streaming_compress_compress(VALUE obj, VALUE src)
|
|
125
131
|
struct streaming_compress_t* sc;
|
126
132
|
TypedData_Get_Struct(obj, struct streaming_compress_t, &streaming_compress_type, sc);
|
127
133
|
|
128
|
-
const char* output_data = RSTRING_PTR(sc->buf);
|
129
134
|
VALUE result = rb_str_new(0, 0);
|
130
135
|
while (input.pos < input.size) {
|
136
|
+
const char* output_data = RSTRING_PTR(sc->buf);
|
131
137
|
ZSTD_outBuffer output = { (void*)output_data, sc->buf_size, 0 };
|
132
138
|
size_t const ret = zstd_stream_compress(sc->ctx, &output, &input, ZSTD_e_continue, false);
|
133
139
|
if (ZSTD_isError(ret)) {
|
@@ -142,10 +148,8 @@ static VALUE
|
|
142
148
|
rb_streaming_compress_write(int argc, VALUE *argv, VALUE obj)
|
143
149
|
{
|
144
150
|
size_t total = 0;
|
145
|
-
VALUE result = rb_str_new(0, 0);
|
146
151
|
struct streaming_compress_t* sc;
|
147
152
|
TypedData_Get_Struct(obj, struct streaming_compress_t, &streaming_compress_type, sc);
|
148
|
-
const char* output_data = RSTRING_PTR(sc->buf);
|
149
153
|
|
150
154
|
while (argc-- > 0) {
|
151
155
|
VALUE str = *argv++;
|
@@ -155,14 +159,20 @@ rb_streaming_compress_write(int argc, VALUE *argv, VALUE obj)
|
|
155
159
|
ZSTD_inBuffer input = { input_data, input_size, 0 };
|
156
160
|
|
157
161
|
while (input.pos < input.size) {
|
162
|
+
const char* output_data = RSTRING_PTR(sc->buf);
|
158
163
|
ZSTD_outBuffer output = { (void*)output_data, sc->buf_size, 0 };
|
159
164
|
size_t const ret = zstd_stream_compress(sc->ctx, &output, &input, ZSTD_e_continue, false);
|
160
165
|
if (ZSTD_isError(ret)) {
|
161
166
|
rb_raise(rb_eRuntimeError, "compress error error code: %s", ZSTD_getErrorName(ret));
|
162
167
|
}
|
163
|
-
|
168
|
+
/* Directly append to the pending buffer */
|
169
|
+
if (output.pos > 0) {
|
170
|
+
rb_str_cat(sc->pending, output.dst, output.pos);
|
171
|
+
}
|
164
172
|
}
|
173
|
+
total += RSTRING_LEN(str);
|
165
174
|
}
|
175
|
+
|
166
176
|
return SIZET2NUM(total);
|
167
177
|
}
|
168
178
|
|
@@ -192,8 +202,11 @@ rb_streaming_compress_flush(VALUE obj)
|
|
192
202
|
{
|
193
203
|
struct streaming_compress_t* sc;
|
194
204
|
TypedData_Get_Struct(obj, struct streaming_compress_t, &streaming_compress_type, sc);
|
195
|
-
VALUE
|
196
|
-
|
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;
|
197
210
|
}
|
198
211
|
|
199
212
|
static VALUE
|
@@ -201,8 +214,11 @@ rb_streaming_compress_finish(VALUE obj)
|
|
201
214
|
{
|
202
215
|
struct streaming_compress_t* sc;
|
203
216
|
TypedData_Get_Struct(obj, struct streaming_compress_t, &streaming_compress_type, sc);
|
204
|
-
VALUE
|
205
|
-
|
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;
|
206
222
|
}
|
207
223
|
|
208
224
|
extern VALUE rb_mZstd, cStreamingCompress;
|
@@ -100,15 +100,22 @@ 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
|
-
|
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
|
}
|
data/ext/zstdruby/zstdruby.c
CHANGED
@@ -39,61 +39,91 @@ static VALUE rb_compress(int argc, VALUE *argv, VALUE self)
|
|
39
39
|
return output;
|
40
40
|
}
|
41
41
|
|
42
|
-
static VALUE
|
43
|
-
|
44
|
-
|
45
|
-
|
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 };
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
output.size += ZSTD_DStreamOutSize();
|
50
|
-
VALUE output_string = rb_str_new(NULL, output.size);
|
51
|
-
output.dst = RSTRING_PTR(output_string);
|
48
|
+
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only);
|
49
|
+
set_decompress_params(dctx, kwargs);
|
52
50
|
|
53
|
-
|
51
|
+
for (;;) {
|
52
|
+
ZSTD_outBuffer o = (ZSTD_outBuffer){ buf, cap, 0 };
|
53
|
+
size_t ret = ZSTD_decompressStream(dctx, &o, &in);
|
54
54
|
if (ZSTD_isError(ret)) {
|
55
|
-
|
56
|
-
rb_raise(rb_eRuntimeError, "
|
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;
|
57
63
|
}
|
58
|
-
rb_str_cat(result, output.dst, output.pos);
|
59
64
|
}
|
60
|
-
|
61
|
-
return
|
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);
|
62
71
|
}
|
63
72
|
|
64
73
|
static VALUE rb_decompress(int argc, VALUE *argv, VALUE self)
|
65
74
|
{
|
66
|
-
VALUE input_value;
|
67
|
-
VALUE kwargs;
|
75
|
+
VALUE input_value, kwargs;
|
68
76
|
rb_scan_args(argc, argv, "10:", &input_value, &kwargs);
|
69
77
|
StringValue(input_value);
|
70
|
-
char* input_data = RSTRING_PTR(input_value);
|
71
|
-
size_t input_size = RSTRING_LEN(input_value);
|
72
|
-
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
73
|
-
if (dctx == NULL) {
|
74
|
-
rb_raise(rb_eRuntimeError, "%s", "ZSTD_createDCtx failed");
|
75
|
-
}
|
76
|
-
set_decompress_params(dctx, kwargs);
|
77
78
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
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
|
+
}
|
87
105
|
|
88
|
-
|
89
|
-
|
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
|
+
}
|
112
|
+
|
113
|
+
VALUE out = decode_one_frame(dctx, in + off, in_size - off, kwargs);
|
90
114
|
|
91
|
-
|
92
|
-
|
93
|
-
|
115
|
+
ZSTD_freeDCtx(dctx);
|
116
|
+
xfree(in);
|
117
|
+
RB_GC_GUARD(input_value);
|
118
|
+
return out;
|
119
|
+
}
|
120
|
+
|
121
|
+
off += 1;
|
94
122
|
}
|
95
|
-
|
96
|
-
|
123
|
+
|
124
|
+
xfree(in);
|
125
|
+
RB_GC_GUARD(input_value);
|
126
|
+
rb_raise(rb_eRuntimeError, "not a zstd frame (magic not found)");
|
97
127
|
}
|
98
128
|
|
99
129
|
static void free_cdict(void *dict)
|
data/lib/zstd-ruby/version.rb
CHANGED
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: 2.0.
|
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: 2025-
|
10
|
+
date: 2025-09-29 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: bundler
|
@@ -188,7 +187,6 @@ homepage: https://github.com/SpringMT/zstd-ruby
|
|
188
187
|
licenses:
|
189
188
|
- MIT
|
190
189
|
metadata: {}
|
191
|
-
post_install_message:
|
192
190
|
rdoc_options: []
|
193
191
|
require_paths:
|
194
192
|
- lib
|
@@ -199,12 +197,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
199
197
|
version: '0'
|
200
198
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
201
199
|
requirements:
|
202
|
-
- - "
|
200
|
+
- - ">="
|
203
201
|
- !ruby/object:Gem::Version
|
204
|
-
version:
|
202
|
+
version: '0'
|
205
203
|
requirements: []
|
206
|
-
rubygems_version: 3.
|
207
|
-
signing_key:
|
204
|
+
rubygems_version: 3.6.2
|
208
205
|
specification_version: 4
|
209
206
|
summary: Ruby binding for zstd(Zstandard - Fast real-time compression algorithm)
|
210
207
|
test_files: []
|