libbin 1.0.5 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e87d96cfea4bd0ff2ca321e9e318eb2afcdddee0764811db35e2a92835396db8
4
- data.tar.gz: e75d3aa6a8374e04db4e84db9eb88bc768a99e3ceff932d0ce26d4f6501ae5e6
3
+ metadata.gz: 8a0a92cec0fde131c6254ad8b5f8a405e68c2a9bd7699a11e7cd24d7e5d0c110
4
+ data.tar.gz: 17732019c6941e79fcfaf233aba722e08b6470e851adae24a01b9e36c90608ca
5
5
  SHA512:
6
- metadata.gz: f9d940fd59641087b72fb734ba2db6833aa0c7b4620205e8e568580ccc64d4e1f49a433ca206ebe474b8e3946417d1a96491bc79ff977435ef442ad35d9590f7
7
- data.tar.gz: 3b04707ce8a3d434596e641dabf1a4a58d95403207d492089029c37f68e4bdf49e568420f7736f426cd95377e7adf1a95ff306d3bcd3c9b0d71544fc541ef156
6
+ metadata.gz: 2caa512271ce77e4f23ad01d5eb9a1c4a9049eefd8578dcc8b69730183b25311a60a0a1ae97674b9f87778f9e9dad09b5fdcb2acb7a4a3d50110b388f03e106a
7
+ data.tar.gz: 600b1878941b3fa53cc9191bc7de026b9f205ce36520915925a6d4664ddba00d92bcdd4c035424d35eb4b97d2eaf732c2339aad785c603ada01790026f1f0f63
@@ -0,0 +1,557 @@
1
+ #include "ruby.h"
2
+ #include "./libbin_c.h"
3
+
4
+ VALUE cDataShape;
5
+ VALUE cDataRange;
6
+ VALUE cScalar;
7
+
8
+ static ID id_read, id_write;
9
+
10
+ static VALUE cScalar_always_align(VALUE self) {
11
+ return Qfalse;
12
+ }
13
+
14
+ /* align() */
15
+ #define MAKE_TYPE_ALIGN(CLASS, MAPPED_TYPE) \
16
+ static VALUE CLASS ## _align(VALUE self) { \
17
+ (void)self; \
18
+ return INT2FIX(sizeof(MAPPED_TYPE)); \
19
+ }
20
+
21
+ /* size(value = nil, previous_offset = 0, parent = nil, index = nil, length = nil) */
22
+ #define MAKE_TYPE_SIZE(CLASS, MAPPED_TYPE) \
23
+ static VALUE CLASS ## _size(int argc, VALUE* argv, VALUE self) { \
24
+ (void)self; \
25
+ VALUE length; \
26
+ rb_scan_args(argc, argv, "05", NULL, NULL, NULL, NULL, &length); \
27
+ if (RTEST(length)) \
28
+ return ULL2NUM(sizeof(MAPPED_TYPE)*NUM2ULL(length)); \
29
+ else \
30
+ return INT2FIX(sizeof(MAPPED_TYPE)); \
31
+ }
32
+
33
+ /* shape(value = nil, previous_offset = 0, parent = nil, index = nil, kind = DataShape, length = nil) */
34
+ #define MAKE_TYPE_SHAPE(CLASS, MAPPED_TYPE) \
35
+ static VALUE CLASS ## _shape(int argc, VALUE* argv, VALUE self) { \
36
+ (void)self; \
37
+ VALUE previous_offset; \
38
+ VALUE kind; \
39
+ VALUE length; \
40
+ rb_scan_args(argc, argv, "06", NULL, &previous_offset, NULL, NULL, &kind, &length); \
41
+ if (NIL_P(previous_offset)) \
42
+ previous_offset = INT2FIX(0); \
43
+ if (NIL_P(kind)) \
44
+ kind = cDataShape; \
45
+ if (NIL_P(length)) \
46
+ length = INT2FIX(1); \
47
+ VALUE args[] = { previous_offset, \
48
+ LL2NUM(NUM2LL(previous_offset) - 1 + NUM2LL(length) * (ptrdiff_t)sizeof(MAPPED_TYPE)) }; \
49
+ return rb_class_new_instance(2, args, kind); \
50
+ }
51
+
52
+ #define MAKE_LOAD_LOOP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT) \
53
+ do { \
54
+ if (RTEST(length)) { \
55
+ res = rb_ary_new_capa(n); \
56
+ long i = 0; \
57
+ for (MAPPED_TYPE *p = data; p != data + n; p++, i++) \
58
+ rb_ary_store(res, i, RUBY_CONVERT(NATIVE_CONVERT(*p))); \
59
+ } else \
60
+ res = RUBY_CONVERT(NATIVE_CONVERT(*data)); \
61
+ } while (0)
62
+
63
+ #define MAKE_LOAD_ENDIAN(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT) \
64
+ do { \
65
+ if (little) \
66
+ MAKE_LOAD_LOOP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT ## _ ## le ); \
67
+ else \
68
+ MAKE_LOAD_LOOP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT ## _ ## be ); \
69
+ } while (0)
70
+
71
+ #define MAKE_LOAD(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT) \
72
+ MAKE_LOAD_LOOP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT)
73
+
74
+ /* load(input, input_big = LibBin::default_big?, parent = nil, index = nil, length = nil) */
75
+ #define MAKE_TYPE_LOAD(CLASS, MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT, LOAD) \
76
+ static VALUE CLASS ## _load(int argc, VALUE* argv, VALUE self) { \
77
+ (void)self; \
78
+ VALUE input; \
79
+ VALUE input_big; \
80
+ VALUE length; \
81
+ rb_scan_args(argc, argv, "14", &input, &input_big, NULL, NULL, &length); \
82
+ if (NIL_P(input_big)) \
83
+ input_big = rb_funcall(mLibBin, rb_intern("default_big?"), 0); \
84
+ unsigned little = RTEST(input_big) ? 0 : 1; \
85
+ long n = RTEST(length) ? NUM2LONG(length) : 1; \
86
+ size_t cnt = sizeof(MAPPED_TYPE) * n; \
87
+ VALUE res; \
88
+ VALUE str = rb_funcall(input, id_read, 1, ULL2NUM(cnt)); \
89
+ if (NIL_P(str) || RSTRING_LEN(str) < (long)cnt) \
90
+ rb_raise(rb_eRuntimeError, \
91
+ "could not read enough data: got %ld needed %zu", \
92
+ NIL_P(str) ? 0 : RSTRING_LEN(str), cnt); \
93
+ MAPPED_TYPE *data = (MAPPED_TYPE *)RSTRING_PTR(str); \
94
+ LOAD(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT); \
95
+ RB_GC_GUARD(str); \
96
+ return res; \
97
+ }
98
+
99
+ #define MAKE_DUMP_LOOP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT) \
100
+ do { \
101
+ if (RTEST(length)) \
102
+ for (long i = 0; i < n; i++) { \
103
+ MAPPED_TYPE v = NATIVE_CONVERT(RUBY_CONVERT(rb_ary_entry(value, i))); \
104
+ rb_str_cat(str, (char *)&v, sizeof(MAPPED_TYPE)); \
105
+ } \
106
+ else { \
107
+ MAPPED_TYPE v = NATIVE_CONVERT(RUBY_CONVERT(value)); \
108
+ rb_str_cat(str, (char *)&v, sizeof(MAPPED_TYPE)); \
109
+ } \
110
+ } while (0)
111
+
112
+ #define MAKE_DUMP_ENDIAN(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT) \
113
+ do { \
114
+ if (little) \
115
+ MAKE_DUMP_LOOP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT ## _ ## le ); \
116
+ else \
117
+ MAKE_DUMP_LOOP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT ## _ ## be ); \
118
+ } while (0)
119
+
120
+ #define MAKE_DUMP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT) \
121
+ MAKE_DUMP_LOOP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT)
122
+
123
+ /* dump(value, output, output_big = LibBin::default_big?, parent = nil, index = nil, length = nil) */
124
+ #define MAKE_TYPE_DUMP(CLASS, MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT, DUMP) \
125
+ static VALUE CLASS ## _dump(int argc, VALUE* argv, VALUE self) { \
126
+ (void)self; \
127
+ VALUE value; \
128
+ VALUE output; \
129
+ VALUE output_big; \
130
+ VALUE length; \
131
+ rb_scan_args(argc, argv, "24", &value, &output, &output_big, NULL, NULL, &length); \
132
+ if (NIL_P(output_big)) \
133
+ output_big = rb_funcall(mLibBin, rb_intern("default_big?"), 0); \
134
+ unsigned little = RTEST(output_big) ? 0 : 1; \
135
+ long n = RTEST(length) ? NUM2LONG(length) : 1; \
136
+ size_t cnt = sizeof(MAPPED_TYPE) * n; \
137
+ VALUE str = rb_str_buf_new((long)cnt); \
138
+ DUMP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT); \
139
+ rb_funcall(output, id_write, 1, str); \
140
+ return Qnil; \
141
+ }
142
+
143
+ #define MAKE_CONVERT_LOOP(MAPPED_TYPE, MAPPED_SWAP, SWAP_COND, RUBY_CONVERT, NATIVE_CONVERT) \
144
+ do { \
145
+ if (RTEST(length)) { \
146
+ res = rb_ary_new_capa(n); \
147
+ long i = 0; \
148
+ for (MAPPED_TYPE *p = data; p != data + n; p++, i++) { \
149
+ rb_ary_store(res, i, RUBY_CONVERT(NATIVE_CONVERT(*p))); \
150
+ if (SWAP_COND) \
151
+ *p = MAPPED_SWAP(*p); \
152
+ } \
153
+ } else { \
154
+ res = RUBY_CONVERT(NATIVE_CONVERT(*data)); \
155
+ if (SWAP_COND) \
156
+ *data = MAPPED_SWAP(*data); \
157
+ } \
158
+ } while(0)
159
+
160
+ #define MAKE_CONVERT_ENDIAN(MAPPED_TYPE, MAPPED_SWAP, RUBY_CONVERT, NATIVE_CONVERT) \
161
+ do { \
162
+ if (little_input) \
163
+ MAKE_CONVERT_LOOP(MAPPED_TYPE, MAPPED_SWAP, !little_output, RUBY_CONVERT, NATIVE_CONVERT ## _ ## le ); \
164
+ else \
165
+ MAKE_CONVERT_LOOP(MAPPED_TYPE, MAPPED_SWAP, little_output, RUBY_CONVERT, NATIVE_CONVERT ## _ ## be ); \
166
+ } while (0)
167
+
168
+ #define MAKE_CONVERT(MAPPED_TYPE, MAPPED_SWAP, RUBY_CONVERT, NATIVE_CONVERT) \
169
+ MAKE_CONVERT_LOOP(MAPPED_TYPE, MAPPED_SWAP, 0, RUBY_CONVERT, NATIVE_CONVERT)
170
+
171
+
172
+ /* convert(input, output, input_big = LibBin::default_big?, output_big = !input_big, parent = nil, index = nil, length = nil) */
173
+ #define MAKE_TYPE_CONVERT(CLASS, MAPPED_TYPE, MAPPED_SWAP, RUBY_CONVERT, NATIVE_CONVERT, CONVERT) \
174
+ static VALUE CLASS ## _convert(int argc, VALUE* argv, VALUE self) { \
175
+ (void)self; \
176
+ VALUE input; \
177
+ VALUE output; \
178
+ VALUE input_big; \
179
+ VALUE output_big; \
180
+ VALUE length; \
181
+ rb_scan_args(argc, argv, "25", &input, &output, &input_big, &output_big, NULL, NULL, &length); \
182
+ if (NIL_P(input_big)) \
183
+ input_big = rb_funcall(mLibBin, rb_intern("default_big?"), 0); \
184
+ unsigned little_input = RTEST(input_big) ? 0 : 1; \
185
+ if (NIL_P(output_big)) \
186
+ output_big = little_input ? Qtrue : Qfalse; \
187
+ unsigned little_output = RTEST(output_big) ? 0 : 1; \
188
+ long n = RTEST(length) ? NUM2LONG(length) : 1; \
189
+ size_t cnt = sizeof(MAPPED_TYPE) * n; \
190
+ VALUE res; \
191
+ VALUE str = rb_funcall(input, id_read, 1, ULL2NUM(cnt)); \
192
+ if (NIL_P(str) || RSTRING_LEN(str) < (long)cnt) \
193
+ rb_raise(rb_eRuntimeError, "could not read enough data: got %ld needed %zu", \
194
+ NIL_P(str) ? 0 : RSTRING_LEN(str), cnt); \
195
+ MAPPED_TYPE *data = (MAPPED_TYPE *)RSTRING_PTR(str); \
196
+ CONVERT(MAPPED_TYPE, MAPPED_SWAP, RUBY_CONVERT, NATIVE_CONVERT); \
197
+ rb_funcall(output, id_write, 1, str); \
198
+ return res; \
199
+ }
200
+
201
+ #define MAKE_CLASS_DEFINE(CLASS_NAME, CLASS) \
202
+ static void define_ ## CLASS() { \
203
+ CLASS = rb_define_class_under(cStructure, #CLASS_NAME, cScalar); \
204
+ rb_define_singleton_method(CLASS, "align", CLASS ## _align, 0); \
205
+ rb_define_singleton_method(CLASS, "size", CLASS ## _size, -1); \
206
+ rb_define_singleton_method(CLASS, "shape", CLASS ## _shape, -1); \
207
+ rb_define_singleton_method(CLASS, "load", CLASS ## _load, -1); \
208
+ rb_define_singleton_method(CLASS, "dump", CLASS ## _dump, -1); \
209
+ rb_define_singleton_method(CLASS, "convert", CLASS ## _convert, -1); \
210
+ }
211
+
212
+ #define MAKE_STATIC_OBJECT(CLASS) \
213
+ static VALUE CLASS;
214
+
215
+ #define MAKE_CLASS_TYPE_ENDIAN_EX(CLASS_NAME, CLASS, MAPPED_TYPE, MAPPED_SWAP, RUBY_CONVERT_TO, RUBY_CONVERT_FROM, NATIVE_CONVERT_TO, NATIVE_CONVERT_FROM, ENDIAN) \
216
+ MAKE_STATIC_OBJECT(CLASS) \
217
+ MAKE_TYPE_ALIGN(CLASS, MAPPED_TYPE) \
218
+ MAKE_TYPE_SIZE(CLASS, MAPPED_TYPE) \
219
+ MAKE_TYPE_SHAPE(CLASS, MAPPED_TYPE) \
220
+ MAKE_TYPE_LOAD(CLASS, MAPPED_TYPE, RUBY_CONVERT_TO, NATIVE_CONVERT_TO, MAKE_LOAD ## ENDIAN) \
221
+ MAKE_TYPE_DUMP(CLASS, MAPPED_TYPE, RUBY_CONVERT_FROM, NATIVE_CONVERT_FROM, MAKE_DUMP ## ENDIAN) \
222
+ MAKE_TYPE_CONVERT(CLASS, MAPPED_TYPE, MAPPED_SWAP, RUBY_CONVERT_TO, NATIVE_CONVERT_TO, MAKE_CONVERT ## ENDIAN) \
223
+ MAKE_CLASS_DEFINE(CLASS_NAME, CLASS)
224
+
225
+ #define MAKE_CLASS_TYPE_ENDIAN(CLASS_NAME, CLASS, MAPPED_TYPE, MAPPED_SWAP, RUBY_CONVERT_TO, RUBY_CONVERT_FROM, NATIVE_CONVERT_TO, NATIVE_CONVERT_FROM, ENDIAN) \
226
+ MAKE_CLASS_TYPE_ENDIAN_EX(CLASS_NAME, CLASS, MAPPED_TYPE, MAPPED_SWAP, RUBY_CONVERT_TO, RUBY_CONVERT_FROM, NATIVE_CONVERT_TO, NATIVE_CONVERT_FROM, ENDIAN)
227
+
228
+ #define ENDIAN_little
229
+ #define ENDIAN_big
230
+ #define ENDIAN_nil _ENDIAN
231
+ #define ENDIAN_suffix_little _le
232
+ #define ENDIAN_suffix_big _be
233
+ #define ENDIAN_suffix_nil
234
+ #define ENDIAN_SUFFIX_little _LE
235
+ #define ENDIAN_SUFFIX_big _BE
236
+ #define ENDIAN_SUFFIX_nil
237
+
238
+ #define MAKE_ENDIAN(ENDIAN) ENDIAN_ ## ENDIAN
239
+ #define MAKE_ENDIAN_suffix(ENDIAN) ENDIAN_suffix_ ## ENDIAN
240
+ #define MAKE_ENDIAN_SUFFIX(ENDIAN) ENDIAN_SUFFIX_ ## ENDIAN
241
+ #define MAKE_CONVERT_NAME_SUFFIX_EX(NAME, SUFFIX) NAME ## SUFFIX
242
+ #define MAKE_CONVERT_NAME_SUFFIX(NAME, SUFFIX) MAKE_CONVERT_NAME_SUFFIX_EX(NAME, SUFFIX)
243
+ #define MAKE_CONVERT_NAME_MAKE_SUFFIX(NAME, ENDIAN, MAKE_SUFFIX) MAKE_CONVERT_NAME_SUFFIX(NAME, MAKE_SUFFIX(ENDIAN))
244
+ #define MAKE_CLASS_NAME(CLASS_NAME, ENDIAN) MAKE_CONVERT_NAME_MAKE_SUFFIX(CLASS_NAME, ENDIAN, MAKE_ENDIAN_SUFFIX)
245
+ #define MAKE_C_CLASS_NAME(CLASS_NAME, ENDIAN) MAKE_CONVERT_NAME_MAKE_SUFFIX(c ## CLASS_NAME, ENDIAN, MAKE_ENDIAN_SUFFIX)
246
+ #define MAKE_CONVERT_NAME(NAME, ENDIAN) MAKE_CONVERT_NAME_MAKE_SUFFIX(NAME, ENDIAN, MAKE_ENDIAN_suffix)
247
+
248
+ #define MAKE_CLASS(CLASS_NAME, SIZE, RUBY_CONVERT_TO, RUBY_CONVERT_FROM, NATIVE_CONVERT_TO, NATIVE_CONVERT_FROM, ENDIAN) \
249
+ MAKE_CLASS_TYPE_ENDIAN(MAKE_CLASS_NAME(CLASS_NAME, ENDIAN), \
250
+ MAKE_C_CLASS_NAME(CLASS_NAME, ENDIAN), \
251
+ uint ## SIZE ## _t, \
252
+ bswap_uint ## SIZE, \
253
+ RUBY_CONVERT_TO, \
254
+ RUBY_CONVERT_FROM, \
255
+ MAKE_CONVERT_NAME(NATIVE_CONVERT_TO, ENDIAN), \
256
+ MAKE_CONVERT_NAME(NATIVE_CONVERT_FROM, ENDIAN), \
257
+ MAKE_ENDIAN(ENDIAN))
258
+
259
+ #define MAKE_CLASSES(CLASS_NAME, SIZE, RUBY_CONVERT_TO, RUBY_CONVERT_FROM, NATIVE_CONVERT_TO, NATIVE_CONVERT_FROM) \
260
+ MAKE_CLASS(CLASS_NAME, SIZE, RUBY_CONVERT_TO, RUBY_CONVERT_FROM, NATIVE_CONVERT_TO, NATIVE_CONVERT_FROM, nil) \
261
+ MAKE_CLASS(CLASS_NAME, SIZE, RUBY_CONVERT_TO, RUBY_CONVERT_FROM, NATIVE_CONVERT_TO, NATIVE_CONVERT_FROM, little) \
262
+ MAKE_CLASS(CLASS_NAME, SIZE, RUBY_CONVERT_TO, RUBY_CONVERT_FROM, NATIVE_CONVERT_TO, NATIVE_CONVERT_FROM, big)
263
+
264
+ #define MAKE_CALL_DEFINE(CLASS_NAME) \
265
+ do { \
266
+ define_ ## CLASS_NAME(); \
267
+ } while (0)
268
+
269
+ #define MAKE_CALL_DEFINE_EX(CLASS_NAME) \
270
+ MAKE_CALL_DEFINE(CLASS_NAME)
271
+
272
+ #define MAKE_CALL_DEFINES(CLASS_NAME) \
273
+ do { \
274
+ MAKE_CALL_DEFINE_EX(MAKE_C_CLASS_NAME(CLASS_NAME, nil)); \
275
+ MAKE_CALL_DEFINE_EX(MAKE_C_CLASS_NAME(CLASS_NAME, little)); \
276
+ MAKE_CALL_DEFINE_EX(MAKE_C_CLASS_NAME(CLASS_NAME, big)); \
277
+ } while (0)
278
+
279
+ static inline float half_to_float_le(uint16_t val) {
280
+ val = unpack_half_le(val);
281
+ union float_u u;
282
+ u.i = half_to_float(val);
283
+ return u.f;
284
+ }
285
+
286
+ static inline float half_to_float_be(uint16_t val) {
287
+ val = unpack_half_be(val);
288
+ union float_u u;
289
+ u.i = half_to_float(val);
290
+ return u.f;
291
+ }
292
+
293
+ static inline uint16_t float_to_half_le(float f) {
294
+ uint16_t res;
295
+ union float_u u;
296
+ u.f = f;
297
+ res = half_from_float(u.i);
298
+ res = pack_half_le(res);
299
+ return res;
300
+ }
301
+
302
+ static inline uint16_t float_to_half_be(float f) {
303
+ uint16_t res;
304
+ union float_u u;
305
+ u.f = f;
306
+ res = half_from_float(u.i);
307
+ res = pack_half_be(res);
308
+ return res;
309
+ }
310
+
311
+
312
+ MAKE_CLASSES(Half, 16, DBL2NUM, NUM2DBL, half_to_float, float_to_half)
313
+
314
+ static inline float pghalf_to_float_le(uint16_t val) {
315
+ val = unpack_pghalf_le(val);
316
+ union float_u u;
317
+ u.i = pghalf_to_float(val);
318
+ return u.f;
319
+ }
320
+
321
+ static inline float pghalf_to_float_be(uint16_t val) {
322
+ val = unpack_pghalf_be(val);
323
+ union float_u u;
324
+ u.i = pghalf_to_float(val);
325
+ return u.f;
326
+ }
327
+
328
+ static inline uint16_t float_to_pghalf_le(float f) {
329
+ uint16_t res;
330
+ union float_u u;
331
+ u.f = f;
332
+ res = pghalf_from_float(u.i);
333
+ res = pack_pghalf_le(res);
334
+ return res;
335
+ }
336
+
337
+ static inline uint16_t float_to_pghalf_be(float f) {
338
+ uint16_t res;
339
+ union float_u u;
340
+ u.f = f;
341
+ res = pghalf_from_float(u.i);
342
+ res = pack_pghalf_be(res);
343
+ return res;
344
+ }
345
+
346
+ MAKE_CLASSES(PGHalf, 16, DBL2NUM, NUM2DBL, pghalf_to_float, float_to_pghalf)
347
+
348
+ MAKE_CLASSES(Int8, 8, INT2FIX, NUM2SHORT, unpack_int8, pack_int8)
349
+ MAKE_CLASSES(UInt8, 8, USHORT2NUM, NUM2USHORT, unpack_uint8, pack_uint8)
350
+ MAKE_CLASSES(Int16, 16, INT2FIX, NUM2SHORT, unpack_int16, pack_int16)
351
+ MAKE_CLASSES(UInt16, 16, USHORT2NUM, NUM2USHORT, unpack_uint16, pack_uint16)
352
+ MAKE_CLASSES(Int32, 32, INT2NUM, NUM2INT, unpack_int32, pack_int32)
353
+ MAKE_CLASSES(UInt32, 32, UINT2NUM, NUM2UINT, unpack_uint32, pack_uint32)
354
+ MAKE_CLASSES(Int64, 64, LL2NUM, NUM2LL, unpack_int64, pack_int64)
355
+ MAKE_CLASSES(UInt64, 64, ULL2NUM, NUM2ULL, unpack_uint64, pack_uint64)
356
+ MAKE_CLASSES(Flt, 32, DBL2NUM, NUM2DBL, unpack_float, pack_float)
357
+ MAKE_CLASSES(Double, 64, DBL2NUM, NUM2DBL, unpack_double, pack_double)
358
+
359
+ static VALUE cStr;
360
+
361
+ static VALUE cStr_align(VALUE self) {
362
+ (void)self;
363
+ return INT2FIX(sizeof(char));
364
+ }
365
+
366
+ static VALUE cStr_size(int argc, VALUE* argv, VALUE self) {
367
+ (void)self;
368
+ VALUE value;
369
+ VALUE length;
370
+ rb_scan_args(argc, argv, "14", &value, NULL, NULL, NULL, &length);
371
+ if (RTEST(length))
372
+ return length;
373
+ else
374
+ return rb_funcall(value, rb_intern("bytesize"), 0);
375
+ }
376
+
377
+ static VALUE cStr_shape(int argc, VALUE* argv, VALUE self) {
378
+ (void)self;
379
+ VALUE value;
380
+ VALUE previous_offset;
381
+ VALUE kind;
382
+ VALUE length;
383
+ rb_scan_args(argc, argv, "15", &value, &previous_offset, NULL, NULL, &kind, &length);
384
+ if (NIL_P(previous_offset))
385
+ previous_offset = INT2FIX(0);
386
+ if (NIL_P(kind))
387
+ kind = cDataShape;
388
+ if (NIL_P(length)) {
389
+ VALUE args[] = { previous_offset, LL2NUM(NUM2LL(previous_offset) - 1 + RSTRING_LEN(value)) };
390
+ return rb_class_new_instance(2, args, kind);
391
+ } else {
392
+ VALUE args[] = { previous_offset, LL2NUM(NUM2LL(previous_offset) - 1 + NUM2LL(length)) };
393
+ return rb_class_new_instance(2, args, kind);
394
+ }
395
+ }
396
+
397
+ static VALUE cStr_load(int argc, VALUE* argv, VALUE self) {
398
+ (void)self;
399
+ VALUE input;
400
+ VALUE length;
401
+ rb_scan_args(argc, argv, "14", &input, NULL, NULL, NULL, &length);
402
+ if (NIL_P(length))
403
+ return rb_funcall(input, rb_intern("readline"), 1, rb_str_new_static("", 1));
404
+ else {
405
+ VALUE str = rb_funcall(input, id_read, 1, length);
406
+ if (NIL_P(str) || RSTRING_LEN(str) < NUM2LONG(length))
407
+ rb_raise(rb_eRuntimeError,
408
+ "could not read enough data: got %ld needed %zu", RSTRING_LEN(str), NUM2LONG(length));
409
+ return str;
410
+ }
411
+ }
412
+
413
+ static VALUE cStr_dump(int argc, VALUE* argv, VALUE self) {
414
+ (void)self;
415
+ VALUE value;
416
+ VALUE output;
417
+ VALUE length;
418
+ rb_scan_args(argc, argv, "24", &value, &output, NULL, NULL, NULL, &length);
419
+ if (NIL_P(length))
420
+ rb_funcall(output, id_write, 1, value);
421
+ else {
422
+ long l = NUM2LONG(length);
423
+ long vl = RSTRING_LEN(value);
424
+ VALUE str;
425
+ if (vl > l)
426
+ str = rb_str_new(RSTRING_PTR(value), l);
427
+ else {
428
+ str = rb_str_buf_new(l);
429
+ rb_str_cat(str, RSTRING_PTR(value), vl);
430
+ for (long i = 0; i < l - vl; i++)
431
+ rb_str_cat(str, "", 1);
432
+ }
433
+ rb_funcall(output, id_write, 1, str);
434
+ }
435
+ return Qnil;
436
+ }
437
+
438
+ static VALUE cStr_convert(int argc, VALUE* argv, VALUE self) {
439
+ (void)self;
440
+ VALUE input;
441
+ VALUE output;
442
+ VALUE length;
443
+ rb_scan_args(argc, argv, "25", &input, &output, NULL, NULL, NULL, NULL, &length);
444
+ VALUE str;
445
+ if (NIL_P(length))
446
+ str = rb_funcall(input, rb_intern("readline"), 1, rb_str_new_static("", 1));
447
+ else {
448
+ str = rb_funcall(input, id_read, 1, length);
449
+ if (NIL_P(str) || RSTRING_LEN(str) < NUM2LONG(length))
450
+ rb_raise(rb_eRuntimeError,
451
+ "could not read enough data: got %ld needed %zu", RSTRING_LEN(str), NUM2LONG(length));
452
+ }
453
+ rb_funcall(output, id_write, 1, str);
454
+ return str;
455
+ }
456
+
457
+ static void define_cStr() {
458
+ cStr = rb_define_class_under(cStructure, "Str", cScalar);
459
+ /**
460
+ * Returns the alignement of the underlying character type.
461
+ * @return [Integer]
462
+ */
463
+ rb_define_singleton_method(cStr, "align", cStr_align, 0);
464
+ /**
465
+ * @overload size(value, offset = 0, parent = nil, index = nil, length = nil)
466
+ * Returns the size of a string.
467
+ * @param value [Object] string to dump.
468
+ * @param offset [Integer] ignored.
469
+ * @param parent [Structure] ignored.
470
+ * @param index [Integer] ignored.
471
+ * @param length [Integer] if given the length of the vector. Else
472
+ * the size of the string.
473
+ * @return [Integer] the size of the string or <tt>sizeof(char) * length</tt>.
474
+ */
475
+ rb_define_singleton_method(cStr, "size", cStr_size, -1);
476
+ /**
477
+ * @overload shape(value, offset = 0, parent = nil, index = nil, kind = DataShape, length = nil)
478
+ * Returns the shape of a string field
479
+ * @param value [Object] ignored.
480
+ * @param offset [Integer] start of the shape.
481
+ * @param parent [Structure] ignored.
482
+ * @param index [Integer] ignored.
483
+ * @param kind [Class] shape class. Will be instantiated through
484
+ * new with the +offset+ and <tt>offset + sizeof($3) * length - 1</tt>.
485
+ * @param length [Integer] if given the length of the string to
486
+ * consider. Else the length is the size of the string.
487
+ * @return [kind] a new instance of +kind+
488
+ */
489
+ rb_define_singleton_method(cStr, "shape", cStr_shape, -1);
490
+ /**
491
+ * @overload load(input, input_big = LibBin::default_big?, parent = nil, index = nil, length = nil)
492
+ * Load a string field from +input+, and return it.
493
+ * @param input [IO] the stream to load the field from.
494
+ * @param input_big [Boolean] the endianness of +input+
495
+ * @param parent [Structure] ignored.
496
+ * @param index [Integer] ignored.
497
+ * @param length [Integer] if given the length of the string. Else
498
+ * the string is considered NULL terminated.
499
+ * @return [String] the Ruby representation of the string.
500
+ */
501
+ rb_define_singleton_method(cStr, "load", cStr_load, -1);
502
+ /**
503
+ * @overload dump(value, output, output_big = LibBin::default_big?, parent = nil, index = nil, length = nil)
504
+ * Dump a string field to +output+.
505
+ * @param value [Numeric, Array<Numeric>] the Ruby representation
506
+ * of the string.
507
+ * @param output [IO] the stream to dump the field to.
508
+ * @param output_big [Boolean] the endianness of +output+.
509
+ * @param parent [Structure] ignored.
510
+ * @param index [Integer] ignored.
511
+ * @param length [Integer] if given the length of the string to dump. Else
512
+ * the length is the size of the string.
513
+ * @return [nil]
514
+ */
515
+ rb_define_singleton_method(cStr, "dump", cStr_dump, -1);
516
+ /**
517
+ * @overload convert(input, output, input_big = LibBin::default_big?, output_big = !input_big, parent = nil, index = nil, length = nil)
518
+ * Convert a string field by loading it from +input+,
519
+ * dumping it to +output+, and returning the loaded field.
520
+ * @param input [IO] the stream to load the field from.
521
+ * @param output [IO] the stream to dump the field to.
522
+ * @param input_big [Boolean] the endianness of +input+
523
+ * @param output_big [Boolean] the endianness of +output+.
524
+ * @param parent [Structure] ignored.
525
+ * @param index [Integer] ignored.
526
+ * @param length [Integer] if given the length of the string to reqd. Else
527
+ * the string is considered NULL terminated.
528
+ * @return [String] the Ruby representation of the string.
529
+ */
530
+ rb_define_singleton_method(cStr, "convert", cStr_convert, -1);
531
+ }
532
+
533
+ void define_cScalar() {
534
+ id_read = rb_intern("read");
535
+ id_write = rb_intern("write");
536
+ cScalar = rb_define_class_under(cStructure, "Scalar", rb_cObject);
537
+ /**
538
+ * Returns false as scalars are not required to be aligned.
539
+ * @return [false] return false.
540
+ */
541
+ rb_define_singleton_method(cScalar, "always_align", cScalar_always_align, 0);
542
+ MAKE_CALL_DEFINES(Half);
543
+ MAKE_CALL_DEFINES(PGHalf);
544
+ MAKE_CALL_DEFINES(Int8);
545
+ MAKE_CALL_DEFINES(UInt8);
546
+ MAKE_CALL_DEFINES(Int16);
547
+ MAKE_CALL_DEFINES(UInt16);
548
+ MAKE_CALL_DEFINES(Int32);
549
+ MAKE_CALL_DEFINES(UInt32);
550
+ MAKE_CALL_DEFINES(Int64);
551
+ MAKE_CALL_DEFINES(UInt64);
552
+ MAKE_CALL_DEFINES(Flt);
553
+ MAKE_CALL_DEFINES(Double);
554
+ define_cStr();
555
+ }
556
+
557
+
@@ -0,0 +1,16 @@
1
+ #ifndef DATA_TYPES_H__
2
+ #define DATA_TYPES_H__
3
+
4
+ union float_u {
5
+ float f;
6
+ uint32_t i;
7
+ };
8
+
9
+ extern VALUE cScalar;
10
+ extern VALUE cDataShape;
11
+ extern VALUE cDataRange;
12
+ extern VALUE cStructure;
13
+
14
+ void define_cScalar();
15
+
16
+ #endif