extbzip3 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/ext/extbzip3.h ADDED
@@ -0,0 +1,279 @@
1
+ #ifndef EXTBZIP3_H
2
+ #define EXTBZIP3_H 1
3
+
4
+ #include <ruby.h>
5
+ #include <ruby/thread.h>
6
+ #include <ruby/version.h>
7
+ #include "extconf.h"
8
+ #include "compat.h"
9
+ #include <libbz3.h>
10
+ #include <ctype.h>
11
+ #include <limits.h>
12
+ #include <stdlib.h>
13
+
14
+ #define RDOCFAKE(...)
15
+
16
+ #if RUBY_API_VERSION_CODE >= 20700
17
+ # define AUX_DEFINE_TYPED_DATA_COMPACT(...) __VA_ARGS__
18
+ #else
19
+ # define AUX_DEFINE_TYPED_DATA_COMPACT(...)
20
+ #endif
21
+
22
+ #define AUX_DEFINE_TYPED_DATA_GC_MARK(FIELD) rb_gc_mark_movable(_data_ptr->FIELD);
23
+ #define AUX_DEFINE_TYPED_DATA_GC_MOVE(FIELD) _data_ptr->FIELD = rb_gc_location(_data_ptr->FIELD);
24
+
25
+ #define AUX_DEFINE_TYPED_DATA(PREFIX, ALLOC_NAME, FREE_BLOCK, GC_VALUE) \
26
+ static void \
27
+ PREFIX ## _free(void *ptr) \
28
+ { \
29
+ if (ptr) { \
30
+ struct PREFIX *_data_ptr = (struct PREFIX *)ptr; \
31
+ \
32
+ do { \
33
+ FREE_BLOCK(_data_ptr) \
34
+ } while (0); \
35
+ \
36
+ xfree(_data_ptr); \
37
+ } \
38
+ } \
39
+ \
40
+ static void \
41
+ PREFIX ## _mark(void *ptr) \
42
+ { \
43
+ struct PREFIX *_data_ptr = (struct PREFIX *)ptr; \
44
+ (void)_data_ptr; \
45
+ \
46
+ GC_VALUE(AUX_DEFINE_TYPED_DATA_GC_MARK) \
47
+ } \
48
+ \
49
+ AUX_DEFINE_TYPED_DATA_COMPACT( \
50
+ static void \
51
+ PREFIX ## _compact(void *ptr) \
52
+ { \
53
+ struct PREFIX *_data_ptr = (struct PREFIX *)ptr; \
54
+ (void)_data_ptr; \
55
+ \
56
+ GC_VALUE(AUX_DEFINE_TYPED_DATA_GC_MOVE) \
57
+ } \
58
+ ) \
59
+ \
60
+ static const rb_data_type_t PREFIX ## _type = { \
61
+ "extbzip3:" #PREFIX, \
62
+ { \
63
+ PREFIX ## _mark, \
64
+ PREFIX ## _free, \
65
+ NULL, /* PREFIX ## _size, */ \
66
+ AUX_DEFINE_TYPED_DATA_COMPACT(PREFIX ## _compact) \
67
+ }, \
68
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY \
69
+ }; \
70
+ \
71
+ static VALUE \
72
+ ALLOC_NAME(VALUE mod) \
73
+ { \
74
+ return rb_data_typed_object_zalloc(mod, sizeof(struct PREFIX), &PREFIX ## _type); \
75
+ } \
76
+ \
77
+ static struct PREFIX * \
78
+ get_ ## PREFIX ## _ptr(VALUE obj) \
79
+ { \
80
+ struct PREFIX *p = (struct PREFIX *)rb_check_typeddata(obj, &PREFIX ## _type); \
81
+ \
82
+ if (!p) { \
83
+ rb_raise(rb_eArgError, "wrong allocated object - %" PRIsVALUE, obj); \
84
+ } \
85
+ \
86
+ return p; \
87
+ } \
88
+ \
89
+ static struct PREFIX * \
90
+ get_ ## PREFIX(VALUE obj) \
91
+ { \
92
+ struct PREFIX *p = get_ ## PREFIX ## _ptr(obj); \
93
+ \
94
+ if (!p->bzip3) { \
95
+ rb_raise(rb_eArgError, "wrong initialized - %" PRIsVALUE, obj); \
96
+ } \
97
+ \
98
+ return p; \
99
+ } \
100
+
101
+
102
+ void extbzip3_init_decoder(VALUE bzip3_module);
103
+ void extbzip3_init_encoder(VALUE bzip3_module);
104
+
105
+ static inline void
106
+ extbzip3_check_error(int status)
107
+ {
108
+ if (status < BZ3_OK) {
109
+ switch (status) {
110
+ case BZ3_ERR_OUT_OF_BOUNDS:
111
+ rb_raise(rb_eRuntimeError, "%s", "BZ3_ERR_OUT_OF_BOUNDS");
112
+ case BZ3_ERR_BWT:
113
+ rb_raise(rb_eRuntimeError, "%s", "BZ3_ERR_BWT");
114
+ case BZ3_ERR_CRC:
115
+ rb_raise(rb_eRuntimeError, "%s", "BZ3_ERR_CRC");
116
+ case BZ3_ERR_MALFORMED_HEADER:
117
+ rb_raise(rb_eRuntimeError, "%s", "BZ3_ERR_MALFORMED_HEADER");
118
+ case BZ3_ERR_TRUNCATED_DATA:
119
+ rb_raise(rb_eRuntimeError, "%s", "BZ3_ERR_TRUNCATED_DATA");
120
+ case BZ3_ERR_DATA_TOO_BIG:
121
+ rb_raise(rb_eRuntimeError, "%s", "BZ3_ERR_DATA_TOO_BIG");
122
+ case BZ3_ERR_INIT:
123
+ rb_raise(rb_eRuntimeError, "%s", "BZ3_ERR_INIT");
124
+ default:
125
+ rb_raise(rb_eRuntimeError, "unknown error (code: %d)", status);
126
+ }
127
+ }
128
+ }
129
+
130
+ #define AUX_BZIP3_BLOCKSIZE_MIN (65 << 10)
131
+ #define AUX_BZIP3_BLOCKSIZE_MAX (511 << 20)
132
+
133
+ #define AUX_BZIP3_V1_FILE_FORMAT 1
134
+ #define AUX_BZIP3_V1_FRAME_FORMAT 2
135
+
136
+ static const char aux_bzip3_signature[5] = { 'B', 'Z', '3', 'v', '1' };
137
+
138
+ static inline int
139
+ aux_conv_to_format(VALUE o)
140
+ {
141
+ if (RB_NIL_OR_UNDEF_P(o)) {
142
+ return AUX_BZIP3_V1_FILE_FORMAT;
143
+ }
144
+
145
+ int n = NUM2INT(o);
146
+
147
+ switch (n) {
148
+ case AUX_BZIP3_V1_FILE_FORMAT:
149
+ case AUX_BZIP3_V1_FRAME_FORMAT:
150
+ return n;
151
+ default:
152
+ rb_raise(rb_eRuntimeError, "wrong format type");
153
+ }
154
+ }
155
+
156
+ static inline struct bz3_state *
157
+ aux_bz3_new(uint32_t blocksize)
158
+ {
159
+ struct bz3_state *p = bz3_new(blocksize);
160
+
161
+ if (!p) {
162
+ rb_gc_start();
163
+ p = bz3_new(blocksize);
164
+
165
+ if (!p) {
166
+ rb_raise(rb_eNoMemError, "probabry out of memory");
167
+ }
168
+ }
169
+
170
+ return p;
171
+ }
172
+
173
+ static inline uint32_t
174
+ aux_conv_to_blocksize(VALUE obj)
175
+ {
176
+ if (RB_NIL_OR_UNDEF_P(obj)) {
177
+ return 16 << 20;
178
+ } else {
179
+ uint32_t blocksize = NUM2UINT(obj);
180
+
181
+ if (blocksize < AUX_BZIP3_BLOCKSIZE_MIN) {
182
+ return AUX_BZIP3_BLOCKSIZE_MIN;
183
+ } else if (blocksize > AUX_BZIP3_BLOCKSIZE_MAX) {
184
+ rb_raise(rb_eArgError, "out of range for blocksize (expect %d..%d, but given %d)",
185
+ AUX_BZIP3_BLOCKSIZE_MIN, AUX_BZIP3_BLOCKSIZE_MAX, (int)blocksize);
186
+ }
187
+
188
+ return blocksize;
189
+ }
190
+ }
191
+
192
+ static inline VALUE
193
+ aux_str_new_recycle(VALUE str, size_t capa)
194
+ {
195
+ if (RB_NIL_P(str)) {
196
+ str = rb_str_new(NULL, 0);
197
+ } else {
198
+ rb_str_set_len(str, 0);
199
+ }
200
+
201
+ rb_str_modify_expand(str, capa);
202
+
203
+ return str;
204
+ }
205
+
206
+ static inline uint32_t
207
+ loadu32le(const void *buf)
208
+ {
209
+ const uint8_t *p = (const uint8_t *)buf;
210
+
211
+ return ((uint32_t)p[0] << 0) |
212
+ ((uint32_t)p[1] << 8) |
213
+ ((uint32_t)p[2] << 16) |
214
+ ((uint32_t)p[3] << 24);
215
+ }
216
+
217
+ static inline void
218
+ storeu32le(void *buf, uint32_t n)
219
+ {
220
+ uint8_t *p = (uint8_t *)buf;
221
+
222
+ p[0] = (n >> 0) & 0xff;
223
+ p[1] = (n >> 8) & 0xff;
224
+ p[2] = (n >> 16) & 0xff;
225
+ p[3] = (n >> 24) & 0xff;
226
+ }
227
+
228
+ struct aux_bz3_decode_block_nogvl_main
229
+ {
230
+ struct bz3_state *bz3;
231
+ uint8_t *buf;
232
+ int32_t buflen;
233
+ int32_t originsize;
234
+ };
235
+
236
+ static inline void *
237
+ aux_bz3_decode_block_nogvl_main(void *opaque)
238
+ {
239
+ struct aux_bz3_decode_block_nogvl_main *p = (struct aux_bz3_decode_block_nogvl_main *)opaque;
240
+ return (void *)(intptr_t)bz3_decode_block(p->bz3, p->buf, p->buflen, p->originsize);
241
+ }
242
+
243
+ static inline int32_t
244
+ aux_bz3_decode_block_nogvl(struct bz3_state *bz3, void *buf, size_t buflen, size_t originsize)
245
+ {
246
+ if (buflen > INT32_MAX || originsize > INT32_MAX) {
247
+ return BZ3_ERR_DATA_TOO_BIG;
248
+ }
249
+
250
+ struct aux_bz3_decode_block_nogvl_main args = { bz3, (uint8_t *)buf, (int32_t)buflen, (int32_t)originsize };
251
+ return (int32_t)(intptr_t)rb_thread_call_without_gvl(aux_bz3_decode_block_nogvl_main, &args, NULL, NULL);
252
+ }
253
+
254
+ struct aux_bz3_encode_block_nogvl_main
255
+ {
256
+ struct bz3_state *bz3;
257
+ uint8_t *buf;
258
+ int32_t buflen;
259
+ };
260
+
261
+ static inline void *
262
+ aux_bz3_encode_block_nogvl_main(void *opaque)
263
+ {
264
+ struct aux_bz3_encode_block_nogvl_main *p = (struct aux_bz3_encode_block_nogvl_main *)opaque;
265
+ return (void *)(intptr_t)bz3_encode_block(p->bz3, p->buf, p->buflen);
266
+ }
267
+
268
+ static inline int32_t
269
+ aux_bz3_encode_block_nogvl(struct bz3_state *bz3, void *buf, size_t buflen)
270
+ {
271
+ if (buflen > INT32_MAX) {
272
+ return BZ3_ERR_DATA_TOO_BIG;
273
+ }
274
+
275
+ struct aux_bz3_encode_block_nogvl_main args = { bz3, (uint8_t *)buf, (int32_t)buflen };
276
+ return (int32_t)(intptr_t)rb_thread_call_without_gvl(aux_bz3_encode_block_nogvl_main, &args, NULL, NULL);
277
+ }
278
+
279
+ #endif // EXTBZIP3_H