ruby-zstds 1.0.0
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 +7 -0
- data/AUTHORS +1 -0
- data/LICENSE +21 -0
- data/README.md +498 -0
- data/ext/extconf.rb +82 -0
- data/ext/zstds_ext/buffer.c +30 -0
- data/ext/zstds_ext/buffer.h +23 -0
- data/ext/zstds_ext/common.h +16 -0
- data/ext/zstds_ext/dictionary.c +106 -0
- data/ext/zstds_ext/dictionary.h +16 -0
- data/ext/zstds_ext/error.c +81 -0
- data/ext/zstds_ext/error.h +35 -0
- data/ext/zstds_ext/io.c +512 -0
- data/ext/zstds_ext/io.h +14 -0
- data/ext/zstds_ext/macro.h +13 -0
- data/ext/zstds_ext/main.c +25 -0
- data/ext/zstds_ext/option.c +287 -0
- data/ext/zstds_ext/option.h +122 -0
- data/ext/zstds_ext/stream/compressor.c +241 -0
- data/ext/zstds_ext/stream/compressor.h +31 -0
- data/ext/zstds_ext/stream/decompressor.c +183 -0
- data/ext/zstds_ext/stream/decompressor.h +29 -0
- data/ext/zstds_ext/string.c +254 -0
- data/ext/zstds_ext/string.h +14 -0
- data/lib/zstds.rb +9 -0
- data/lib/zstds/dictionary.rb +47 -0
- data/lib/zstds/error.rb +22 -0
- data/lib/zstds/file.rb +46 -0
- data/lib/zstds/option.rb +194 -0
- data/lib/zstds/stream/abstract.rb +153 -0
- data/lib/zstds/stream/delegates.rb +36 -0
- data/lib/zstds/stream/raw/abstract.rb +55 -0
- data/lib/zstds/stream/raw/compressor.rb +101 -0
- data/lib/zstds/stream/raw/decompressor.rb +70 -0
- data/lib/zstds/stream/reader.rb +166 -0
- data/lib/zstds/stream/reader_helpers.rb +192 -0
- data/lib/zstds/stream/stat.rb +78 -0
- data/lib/zstds/stream/writer.rb +145 -0
- data/lib/zstds/stream/writer_helpers.rb +93 -0
- data/lib/zstds/string.rb +31 -0
- data/lib/zstds/validation.rb +48 -0
- data/lib/zstds/version.rb +6 -0
- metadata +182 -0
@@ -0,0 +1,241 @@
|
|
1
|
+
// Ruby bindings for zstd library.
|
2
|
+
// Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
#include "zstds_ext/stream/compressor.h"
|
5
|
+
|
6
|
+
#include <stdint.h>
|
7
|
+
#include <stdlib.h>
|
8
|
+
#include <zstd.h>
|
9
|
+
|
10
|
+
#include "ruby.h"
|
11
|
+
#include "zstds_ext/common.h"
|
12
|
+
#include "zstds_ext/error.h"
|
13
|
+
#include "zstds_ext/option.h"
|
14
|
+
|
15
|
+
static void free_compressor(zstds_ext_compressor_t* compressor_ptr)
|
16
|
+
{
|
17
|
+
ZSTD_CCtx* ctx = compressor_ptr->ctx;
|
18
|
+
if (ctx != NULL) {
|
19
|
+
ZSTD_freeCCtx(ctx);
|
20
|
+
}
|
21
|
+
|
22
|
+
uint8_t* destination_buffer = compressor_ptr->destination_buffer;
|
23
|
+
if (destination_buffer != NULL) {
|
24
|
+
free(destination_buffer);
|
25
|
+
}
|
26
|
+
|
27
|
+
free(compressor_ptr);
|
28
|
+
}
|
29
|
+
|
30
|
+
VALUE zstds_ext_allocate_compressor(VALUE klass)
|
31
|
+
{
|
32
|
+
zstds_ext_compressor_t* compressor_ptr;
|
33
|
+
|
34
|
+
VALUE self = Data_Make_Struct(klass, zstds_ext_compressor_t, NULL, free_compressor, compressor_ptr);
|
35
|
+
|
36
|
+
compressor_ptr->ctx = NULL;
|
37
|
+
compressor_ptr->destination_buffer = NULL;
|
38
|
+
compressor_ptr->destination_buffer_length = 0;
|
39
|
+
compressor_ptr->remaining_destination_buffer = NULL;
|
40
|
+
compressor_ptr->remaining_destination_buffer_length = 0;
|
41
|
+
|
42
|
+
return self;
|
43
|
+
}
|
44
|
+
|
45
|
+
#define GET_COMPRESSOR(self) \
|
46
|
+
zstds_ext_compressor_t* compressor_ptr; \
|
47
|
+
Data_Get_Struct(self, zstds_ext_compressor_t, compressor_ptr);
|
48
|
+
|
49
|
+
VALUE zstds_ext_initialize_compressor(VALUE self, VALUE options)
|
50
|
+
{
|
51
|
+
GET_COMPRESSOR(self);
|
52
|
+
Check_Type(options, T_HASH);
|
53
|
+
ZSTDS_EXT_GET_COMPRESSOR_OPTIONS(options);
|
54
|
+
ZSTDS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
|
55
|
+
|
56
|
+
ZSTD_CCtx* ctx = ZSTD_createCCtx();
|
57
|
+
if (ctx == NULL) {
|
58
|
+
zstds_ext_raise_error(ZSTDS_EXT_ERROR_ALLOCATE_FAILED);
|
59
|
+
}
|
60
|
+
|
61
|
+
zstds_ext_result_t ext_result = zstds_ext_set_compressor_options(ctx, &compressor_options);
|
62
|
+
if (ext_result != 0) {
|
63
|
+
ZSTD_freeCCtx(ctx);
|
64
|
+
zstds_ext_raise_error(ext_result);
|
65
|
+
}
|
66
|
+
|
67
|
+
if (destination_buffer_length == 0) {
|
68
|
+
destination_buffer_length = ZSTD_CStreamOutSize();
|
69
|
+
}
|
70
|
+
|
71
|
+
uint8_t* destination_buffer = malloc(destination_buffer_length);
|
72
|
+
if (destination_buffer == NULL) {
|
73
|
+
ZSTD_freeCCtx(ctx);
|
74
|
+
zstds_ext_raise_error(ZSTDS_EXT_ERROR_ALLOCATE_FAILED);
|
75
|
+
}
|
76
|
+
|
77
|
+
compressor_ptr->ctx = ctx;
|
78
|
+
compressor_ptr->destination_buffer = destination_buffer;
|
79
|
+
compressor_ptr->destination_buffer_length = destination_buffer_length;
|
80
|
+
compressor_ptr->remaining_destination_buffer = destination_buffer;
|
81
|
+
compressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
|
82
|
+
|
83
|
+
return Qnil;
|
84
|
+
}
|
85
|
+
|
86
|
+
#define DO_NOT_USE_AFTER_CLOSE(compressor_ptr) \
|
87
|
+
if (compressor_ptr->ctx == NULL || compressor_ptr->destination_buffer == NULL) { \
|
88
|
+
zstds_ext_raise_error(ZSTDS_EXT_ERROR_USED_AFTER_CLOSE); \
|
89
|
+
}
|
90
|
+
|
91
|
+
#define GET_SOURCE_DATA(source_value) \
|
92
|
+
Check_Type(source_value, T_STRING); \
|
93
|
+
\
|
94
|
+
const char* source = RSTRING_PTR(source_value); \
|
95
|
+
size_t source_length = RSTRING_LEN(source_value);
|
96
|
+
|
97
|
+
VALUE zstds_ext_compress(VALUE self, VALUE source_value)
|
98
|
+
{
|
99
|
+
GET_COMPRESSOR(self);
|
100
|
+
DO_NOT_USE_AFTER_CLOSE(compressor_ptr);
|
101
|
+
GET_SOURCE_DATA(source_value);
|
102
|
+
|
103
|
+
ZSTD_inBuffer in_buffer;
|
104
|
+
in_buffer.src = source;
|
105
|
+
in_buffer.size = source_length;
|
106
|
+
in_buffer.pos = 0;
|
107
|
+
|
108
|
+
ZSTD_outBuffer out_buffer;
|
109
|
+
out_buffer.dst = compressor_ptr->remaining_destination_buffer;
|
110
|
+
out_buffer.size = compressor_ptr->remaining_destination_buffer_length;
|
111
|
+
out_buffer.pos = 0;
|
112
|
+
|
113
|
+
zstds_result_t result = ZSTD_compressStream2(compressor_ptr->ctx, &out_buffer, &in_buffer, ZSTD_e_continue);
|
114
|
+
if (ZSTD_isError(result)) {
|
115
|
+
zstds_ext_raise_error(zstds_ext_get_error(ZSTD_getErrorCode(result)));
|
116
|
+
}
|
117
|
+
|
118
|
+
compressor_ptr->remaining_destination_buffer += out_buffer.pos;
|
119
|
+
compressor_ptr->remaining_destination_buffer_length -= out_buffer.pos;
|
120
|
+
|
121
|
+
VALUE bytes_written = SIZET2NUM(in_buffer.pos);
|
122
|
+
VALUE needs_more_destination = compressor_ptr->remaining_destination_buffer_length == 0 ? Qtrue : Qfalse;
|
123
|
+
|
124
|
+
return rb_ary_new_from_args(2, bytes_written, needs_more_destination);
|
125
|
+
}
|
126
|
+
|
127
|
+
VALUE zstds_ext_flush_compressor(VALUE self)
|
128
|
+
{
|
129
|
+
GET_COMPRESSOR(self);
|
130
|
+
DO_NOT_USE_AFTER_CLOSE(compressor_ptr);
|
131
|
+
|
132
|
+
ZSTD_inBuffer in_buffer;
|
133
|
+
in_buffer.src = NULL;
|
134
|
+
in_buffer.size = 0;
|
135
|
+
in_buffer.pos = 0;
|
136
|
+
|
137
|
+
ZSTD_outBuffer out_buffer;
|
138
|
+
out_buffer.dst = compressor_ptr->remaining_destination_buffer;
|
139
|
+
out_buffer.size = compressor_ptr->remaining_destination_buffer_length;
|
140
|
+
out_buffer.pos = 0;
|
141
|
+
|
142
|
+
zstds_result_t result = ZSTD_compressStream2(compressor_ptr->ctx, &out_buffer, &in_buffer, ZSTD_e_flush);
|
143
|
+
if (ZSTD_isError(result)) {
|
144
|
+
zstds_ext_raise_error(zstds_ext_get_error(ZSTD_getErrorCode(result)));
|
145
|
+
}
|
146
|
+
|
147
|
+
compressor_ptr->remaining_destination_buffer += out_buffer.pos;
|
148
|
+
compressor_ptr->remaining_destination_buffer_length -= out_buffer.pos;
|
149
|
+
|
150
|
+
VALUE needs_more_destination = result != 0 ? Qtrue : Qfalse;
|
151
|
+
|
152
|
+
return needs_more_destination;
|
153
|
+
}
|
154
|
+
|
155
|
+
VALUE zstds_ext_finish_compressor(VALUE self)
|
156
|
+
{
|
157
|
+
GET_COMPRESSOR(self);
|
158
|
+
DO_NOT_USE_AFTER_CLOSE(compressor_ptr);
|
159
|
+
|
160
|
+
ZSTD_inBuffer in_buffer;
|
161
|
+
in_buffer.src = NULL;
|
162
|
+
in_buffer.size = 0;
|
163
|
+
in_buffer.pos = 0;
|
164
|
+
|
165
|
+
ZSTD_outBuffer out_buffer;
|
166
|
+
out_buffer.dst = compressor_ptr->remaining_destination_buffer;
|
167
|
+
out_buffer.size = compressor_ptr->remaining_destination_buffer_length;
|
168
|
+
out_buffer.pos = 0;
|
169
|
+
|
170
|
+
zstds_result_t result = ZSTD_compressStream2(compressor_ptr->ctx, &out_buffer, &in_buffer, ZSTD_e_end);
|
171
|
+
if (ZSTD_isError(result)) {
|
172
|
+
zstds_ext_raise_error(zstds_ext_get_error(ZSTD_getErrorCode(result)));
|
173
|
+
}
|
174
|
+
|
175
|
+
compressor_ptr->remaining_destination_buffer += out_buffer.pos;
|
176
|
+
compressor_ptr->remaining_destination_buffer_length -= out_buffer.pos;
|
177
|
+
|
178
|
+
VALUE needs_more_destination = result != 0 ? Qtrue : Qfalse;
|
179
|
+
|
180
|
+
return needs_more_destination;
|
181
|
+
}
|
182
|
+
|
183
|
+
VALUE zstds_ext_compressor_read_result(VALUE self)
|
184
|
+
{
|
185
|
+
GET_COMPRESSOR(self);
|
186
|
+
DO_NOT_USE_AFTER_CLOSE(compressor_ptr);
|
187
|
+
|
188
|
+
uint8_t* destination_buffer = compressor_ptr->destination_buffer;
|
189
|
+
size_t destination_buffer_length = compressor_ptr->destination_buffer_length;
|
190
|
+
size_t remaining_destination_buffer_length = compressor_ptr->remaining_destination_buffer_length;
|
191
|
+
|
192
|
+
const char* result = (const char*)destination_buffer;
|
193
|
+
size_t result_length = destination_buffer_length - remaining_destination_buffer_length;
|
194
|
+
|
195
|
+
VALUE result_value = rb_str_new(result, result_length);
|
196
|
+
|
197
|
+
compressor_ptr->remaining_destination_buffer = destination_buffer;
|
198
|
+
compressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
|
199
|
+
|
200
|
+
return result_value;
|
201
|
+
}
|
202
|
+
|
203
|
+
VALUE zstds_ext_compressor_close(VALUE self)
|
204
|
+
{
|
205
|
+
GET_COMPRESSOR(self);
|
206
|
+
DO_NOT_USE_AFTER_CLOSE(compressor_ptr);
|
207
|
+
|
208
|
+
ZSTD_CCtx* ctx = compressor_ptr->ctx;
|
209
|
+
if (ctx != NULL) {
|
210
|
+
ZSTD_freeCCtx(ctx);
|
211
|
+
|
212
|
+
compressor_ptr->ctx = NULL;
|
213
|
+
}
|
214
|
+
|
215
|
+
uint8_t* destination_buffer = compressor_ptr->destination_buffer;
|
216
|
+
if (destination_buffer != NULL) {
|
217
|
+
free(destination_buffer);
|
218
|
+
|
219
|
+
compressor_ptr->destination_buffer = NULL;
|
220
|
+
}
|
221
|
+
|
222
|
+
// It is possible to keep "destination_buffer_length", "remaining_destination_buffer"
|
223
|
+
// and "remaining_destination_buffer_length" as is.
|
224
|
+
|
225
|
+
return Qnil;
|
226
|
+
}
|
227
|
+
|
228
|
+
void zstds_ext_compressor_exports(VALUE root_module)
|
229
|
+
{
|
230
|
+
VALUE module = rb_define_module_under(root_module, "Stream");
|
231
|
+
|
232
|
+
VALUE compressor = rb_define_class_under(module, "NativeCompressor", rb_cObject);
|
233
|
+
|
234
|
+
rb_define_alloc_func(compressor, zstds_ext_allocate_compressor);
|
235
|
+
rb_define_method(compressor, "initialize", zstds_ext_initialize_compressor, 1);
|
236
|
+
rb_define_method(compressor, "write", zstds_ext_compress, 1);
|
237
|
+
rb_define_method(compressor, "flush", zstds_ext_flush_compressor, 0);
|
238
|
+
rb_define_method(compressor, "finish", zstds_ext_finish_compressor, 0);
|
239
|
+
rb_define_method(compressor, "read_result", zstds_ext_compressor_read_result, 0);
|
240
|
+
rb_define_method(compressor, "close", zstds_ext_compressor_close, 0);
|
241
|
+
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
// Ruby bindings for zstd library.
|
2
|
+
// Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
#if !defined(ZSTDS_EXT_STREAM_COMPRESSOR_H)
|
5
|
+
#define ZSTDS_EXT_STREAM_COMPRESSOR_H
|
6
|
+
|
7
|
+
#include <stdint.h>
|
8
|
+
#include <stdlib.h>
|
9
|
+
#include <zstd.h>
|
10
|
+
|
11
|
+
#include "ruby.h"
|
12
|
+
|
13
|
+
typedef struct {
|
14
|
+
ZSTD_CCtx* ctx;
|
15
|
+
uint8_t* destination_buffer;
|
16
|
+
size_t destination_buffer_length;
|
17
|
+
uint8_t* remaining_destination_buffer;
|
18
|
+
size_t remaining_destination_buffer_length;
|
19
|
+
} zstds_ext_compressor_t;
|
20
|
+
|
21
|
+
VALUE zstds_ext_allocate_compressor(VALUE klass);
|
22
|
+
VALUE zstds_ext_initialize_compressor(VALUE self, VALUE options);
|
23
|
+
VALUE zstds_ext_compress(VALUE self, VALUE source);
|
24
|
+
VALUE zstds_ext_flush_compressor(VALUE self);
|
25
|
+
VALUE zstds_ext_finish_compressor(VALUE self);
|
26
|
+
VALUE zstds_ext_compressor_read_result(VALUE self);
|
27
|
+
VALUE zstds_ext_compressor_close(VALUE self);
|
28
|
+
|
29
|
+
void zstds_ext_compressor_exports(VALUE root_module);
|
30
|
+
|
31
|
+
#endif // ZSTDS_EXT_STREAM_COMPRESSOR_H
|
@@ -0,0 +1,183 @@
|
|
1
|
+
// Ruby bindings for zstd library.
|
2
|
+
// Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
#include "zstds_ext/stream/decompressor.h"
|
5
|
+
|
6
|
+
#include <stdint.h>
|
7
|
+
#include <stdlib.h>
|
8
|
+
#include <zstd.h>
|
9
|
+
|
10
|
+
#include "ruby.h"
|
11
|
+
#include "zstds_ext/common.h"
|
12
|
+
#include "zstds_ext/error.h"
|
13
|
+
#include "zstds_ext/option.h"
|
14
|
+
|
15
|
+
static void free_decompressor(zstds_ext_decompressor_t* decompressor_ptr)
|
16
|
+
{
|
17
|
+
ZSTD_DCtx* ctx = decompressor_ptr->ctx;
|
18
|
+
if (ctx != NULL) {
|
19
|
+
ZSTD_freeDCtx(ctx);
|
20
|
+
}
|
21
|
+
|
22
|
+
uint8_t* destination_buffer = decompressor_ptr->destination_buffer;
|
23
|
+
if (destination_buffer != NULL) {
|
24
|
+
free(destination_buffer);
|
25
|
+
}
|
26
|
+
|
27
|
+
free(decompressor_ptr);
|
28
|
+
}
|
29
|
+
|
30
|
+
VALUE zstds_ext_allocate_decompressor(VALUE klass)
|
31
|
+
{
|
32
|
+
zstds_ext_decompressor_t* decompressor_ptr;
|
33
|
+
|
34
|
+
VALUE self = Data_Make_Struct(klass, zstds_ext_decompressor_t, NULL, free_decompressor, decompressor_ptr);
|
35
|
+
|
36
|
+
decompressor_ptr->ctx = NULL;
|
37
|
+
decompressor_ptr->destination_buffer = NULL;
|
38
|
+
decompressor_ptr->destination_buffer_length = 0;
|
39
|
+
decompressor_ptr->remaining_destination_buffer = NULL;
|
40
|
+
decompressor_ptr->remaining_destination_buffer_length = 0;
|
41
|
+
|
42
|
+
return self;
|
43
|
+
}
|
44
|
+
|
45
|
+
#define GET_DECOMPRESSOR(self) \
|
46
|
+
zstds_ext_decompressor_t* decompressor_ptr; \
|
47
|
+
Data_Get_Struct(self, zstds_ext_decompressor_t, decompressor_ptr);
|
48
|
+
|
49
|
+
VALUE zstds_ext_initialize_decompressor(VALUE self, VALUE options)
|
50
|
+
{
|
51
|
+
GET_DECOMPRESSOR(self);
|
52
|
+
Check_Type(options, T_HASH);
|
53
|
+
ZSTDS_EXT_GET_DECOMPRESSOR_OPTIONS(options);
|
54
|
+
ZSTDS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
|
55
|
+
|
56
|
+
ZSTD_DCtx* ctx = ZSTD_createDCtx();
|
57
|
+
if (ctx == NULL) {
|
58
|
+
zstds_ext_raise_error(ZSTDS_EXT_ERROR_ALLOCATE_FAILED);
|
59
|
+
}
|
60
|
+
|
61
|
+
zstds_ext_result_t ext_result = zstds_ext_set_decompressor_options(ctx, &decompressor_options);
|
62
|
+
if (ext_result != 0) {
|
63
|
+
ZSTD_freeDCtx(ctx);
|
64
|
+
zstds_ext_raise_error(ext_result);
|
65
|
+
}
|
66
|
+
|
67
|
+
if (destination_buffer_length == 0) {
|
68
|
+
destination_buffer_length = ZSTD_DStreamOutSize();
|
69
|
+
}
|
70
|
+
|
71
|
+
uint8_t* destination_buffer = malloc(destination_buffer_length);
|
72
|
+
if (destination_buffer == NULL) {
|
73
|
+
ZSTD_freeDCtx(ctx);
|
74
|
+
zstds_ext_raise_error(ZSTDS_EXT_ERROR_ALLOCATE_FAILED);
|
75
|
+
}
|
76
|
+
|
77
|
+
decompressor_ptr->ctx = ctx;
|
78
|
+
decompressor_ptr->destination_buffer = destination_buffer;
|
79
|
+
decompressor_ptr->destination_buffer_length = destination_buffer_length;
|
80
|
+
decompressor_ptr->remaining_destination_buffer = destination_buffer;
|
81
|
+
decompressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
|
82
|
+
|
83
|
+
return Qnil;
|
84
|
+
}
|
85
|
+
|
86
|
+
#define DO_NOT_USE_AFTER_CLOSE(decompressor_ptr) \
|
87
|
+
if (decompressor_ptr->ctx == NULL || decompressor_ptr->destination_buffer == NULL) { \
|
88
|
+
zstds_ext_raise_error(ZSTDS_EXT_ERROR_USED_AFTER_CLOSE); \
|
89
|
+
}
|
90
|
+
|
91
|
+
#define GET_SOURCE_DATA(source_value) \
|
92
|
+
Check_Type(source_value, T_STRING); \
|
93
|
+
\
|
94
|
+
const char* source = RSTRING_PTR(source_value); \
|
95
|
+
size_t source_length = RSTRING_LEN(source_value);
|
96
|
+
|
97
|
+
VALUE zstds_ext_decompress(VALUE self, VALUE source_value)
|
98
|
+
{
|
99
|
+
GET_DECOMPRESSOR(self);
|
100
|
+
DO_NOT_USE_AFTER_CLOSE(decompressor_ptr);
|
101
|
+
GET_SOURCE_DATA(source_value);
|
102
|
+
|
103
|
+
ZSTD_inBuffer in_buffer;
|
104
|
+
in_buffer.src = source;
|
105
|
+
in_buffer.size = source_length;
|
106
|
+
in_buffer.pos = 0;
|
107
|
+
|
108
|
+
ZSTD_outBuffer out_buffer;
|
109
|
+
out_buffer.dst = decompressor_ptr->remaining_destination_buffer;
|
110
|
+
out_buffer.size = decompressor_ptr->remaining_destination_buffer_length;
|
111
|
+
out_buffer.pos = 0;
|
112
|
+
|
113
|
+
zstds_result_t result = ZSTD_decompressStream(decompressor_ptr->ctx, &out_buffer, &in_buffer);
|
114
|
+
if (ZSTD_isError(result)) {
|
115
|
+
zstds_ext_raise_error(zstds_ext_get_error(ZSTD_getErrorCode(result)));
|
116
|
+
}
|
117
|
+
|
118
|
+
decompressor_ptr->remaining_destination_buffer += out_buffer.pos;
|
119
|
+
decompressor_ptr->remaining_destination_buffer_length -= out_buffer.pos;
|
120
|
+
|
121
|
+
VALUE bytes_read = SIZET2NUM(in_buffer.pos);
|
122
|
+
VALUE needs_more_destination = decompressor_ptr->remaining_destination_buffer_length == 0 ? Qtrue : Qfalse;
|
123
|
+
|
124
|
+
return rb_ary_new_from_args(2, bytes_read, needs_more_destination);
|
125
|
+
}
|
126
|
+
|
127
|
+
VALUE zstds_ext_decompressor_read_result(VALUE self)
|
128
|
+
{
|
129
|
+
GET_DECOMPRESSOR(self);
|
130
|
+
DO_NOT_USE_AFTER_CLOSE(decompressor_ptr);
|
131
|
+
|
132
|
+
uint8_t* destination_buffer = decompressor_ptr->destination_buffer;
|
133
|
+
size_t destination_buffer_length = decompressor_ptr->destination_buffer_length;
|
134
|
+
size_t remaining_destination_buffer_length = decompressor_ptr->remaining_destination_buffer_length;
|
135
|
+
|
136
|
+
const char* result = (const char*)destination_buffer;
|
137
|
+
size_t result_length = destination_buffer_length - remaining_destination_buffer_length;
|
138
|
+
|
139
|
+
VALUE result_value = rb_str_new(result, result_length);
|
140
|
+
|
141
|
+
decompressor_ptr->remaining_destination_buffer = destination_buffer;
|
142
|
+
decompressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
|
143
|
+
|
144
|
+
return result_value;
|
145
|
+
}
|
146
|
+
|
147
|
+
VALUE zstds_ext_decompressor_close(VALUE self)
|
148
|
+
{
|
149
|
+
GET_DECOMPRESSOR(self);
|
150
|
+
DO_NOT_USE_AFTER_CLOSE(decompressor_ptr);
|
151
|
+
|
152
|
+
ZSTD_DCtx* ctx = decompressor_ptr->ctx;
|
153
|
+
if (ctx != NULL) {
|
154
|
+
ZSTD_freeDCtx(ctx);
|
155
|
+
|
156
|
+
decompressor_ptr->ctx = NULL;
|
157
|
+
}
|
158
|
+
|
159
|
+
uint8_t* destination_buffer = decompressor_ptr->destination_buffer;
|
160
|
+
if (destination_buffer != NULL) {
|
161
|
+
free(destination_buffer);
|
162
|
+
|
163
|
+
decompressor_ptr->destination_buffer = NULL;
|
164
|
+
}
|
165
|
+
|
166
|
+
// It is possible to keep "destination_buffer_length", "remaining_destination_buffer"
|
167
|
+
// and "remaining_destination_buffer_length" as is.
|
168
|
+
|
169
|
+
return Qnil;
|
170
|
+
}
|
171
|
+
|
172
|
+
void zstds_ext_decompressor_exports(VALUE root_module)
|
173
|
+
{
|
174
|
+
VALUE module = rb_define_module_under(root_module, "Stream");
|
175
|
+
|
176
|
+
VALUE decompressor = rb_define_class_under(module, "NativeDecompressor", rb_cObject);
|
177
|
+
|
178
|
+
rb_define_alloc_func(decompressor, zstds_ext_allocate_decompressor);
|
179
|
+
rb_define_method(decompressor, "initialize", zstds_ext_initialize_decompressor, 1);
|
180
|
+
rb_define_method(decompressor, "read", zstds_ext_decompress, 1);
|
181
|
+
rb_define_method(decompressor, "read_result", zstds_ext_decompressor_read_result, 0);
|
182
|
+
rb_define_method(decompressor, "close", zstds_ext_decompressor_close, 0);
|
183
|
+
}
|