libbin 1.0.7 → 1.0.8
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/libbin/data_types.c +466 -0
- data/ext/libbin/data_types.h +15 -0
- data/ext/libbin/libbin_c.c +1450 -41
- data/ext/libbin/libbin_c.h +12 -0
- data/ext/libbin/libbin_endian.h +126 -0
- data/lib/libbin/data_types.rb +56 -353
- data/lib/libbin.rb +7 -351
- data/libbin.gemspec +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac7b79d2e9bfeed5936680b7b192091988b66bebf8b7a9606468212f176929ae
|
4
|
+
data.tar.gz: 273e0156acc7f86fb799f7b5aafc99c3fb428ac69bcbe5fbda2a265d9543fb04
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1268f8a9247714f2f2dac82b929f559eba7a8561b75f6fa89474e8a3d12b88723d37a6d065b679c41861dd3454a7a19b6d4e41f415a76f8fb77fa5ae3fed1a7d
|
7
|
+
data.tar.gz: e9dd37966771af9750ec9a302048cd14e156d7fd1f4c82c5336f1db50a96e00b9a1b5d04627a21abec24f725556c8fd1dbb9808be567bf09ba429c7b66d5e13a
|
@@ -0,0 +1,466 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "./libbin_c.h"
|
3
|
+
|
4
|
+
VALUE cDataShape;
|
5
|
+
VALUE cScalar;
|
6
|
+
|
7
|
+
static ID id_read, id_write;
|
8
|
+
|
9
|
+
/* size(value, previous_offset = 0, parent = nil, index = nil, length = nil)*/
|
10
|
+
#define MAKE_TYPE_SIZE(CLASS, MAPPED_TYPE) \
|
11
|
+
static VALUE CLASS ## _size(int argc, VALUE* argv, VALUE self) { \
|
12
|
+
(void)self; \
|
13
|
+
VALUE length; \
|
14
|
+
rb_scan_args(argc, argv, "14", NULL, NULL, NULL, NULL, &length); \
|
15
|
+
if (RTEST(length)) \
|
16
|
+
return ULL2NUM(sizeof(MAPPED_TYPE)*NUM2ULL(length)); \
|
17
|
+
else \
|
18
|
+
return INT2FIX(sizeof(MAPPED_TYPE)); \
|
19
|
+
}
|
20
|
+
|
21
|
+
/* shape(value, previous_offset = 0, parent = nil, index = nil, kind = DataShape, length = nil) */
|
22
|
+
#define MAKE_TYPE_SHAPE(CLASS, MAPPED_TYPE) \
|
23
|
+
static VALUE CLASS ## _shape(int argc, VALUE* argv, VALUE self) { \
|
24
|
+
(void)self; \
|
25
|
+
VALUE previous_offset; \
|
26
|
+
VALUE kind; \
|
27
|
+
VALUE length; \
|
28
|
+
rb_scan_args(argc, argv, "15", NULL, &previous_offset, NULL, NULL, &kind, &length); \
|
29
|
+
if (NIL_P(previous_offset)) \
|
30
|
+
previous_offset = INT2FIX(0); \
|
31
|
+
if (NIL_P(kind)) \
|
32
|
+
kind = cDataShape; \
|
33
|
+
if (NIL_P(length)) \
|
34
|
+
length = INT2FIX(1); \
|
35
|
+
VALUE args[] = { previous_offset, \
|
36
|
+
LL2NUM(NUM2LL(previous_offset) - 1 + NUM2LL(length) * (ptrdiff_t)sizeof(MAPPED_TYPE)) }; \
|
37
|
+
return rb_class_new_instance(2, args, kind); \
|
38
|
+
}
|
39
|
+
|
40
|
+
#define MAKE_LOAD_LOOP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT) \
|
41
|
+
do { \
|
42
|
+
if (RTEST(length)) { \
|
43
|
+
res = rb_ary_new_capa(n); \
|
44
|
+
long i = 0; \
|
45
|
+
for (MAPPED_TYPE *p = data; p != data + n; p++, i++) \
|
46
|
+
rb_ary_store(res, i, RUBY_CONVERT(NATIVE_CONVERT(*p))); \
|
47
|
+
} else \
|
48
|
+
res = RUBY_CONVERT(NATIVE_CONVERT(*data)); \
|
49
|
+
} while (0)
|
50
|
+
|
51
|
+
#define MAKE_LOAD_ENDIAN(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT) \
|
52
|
+
do { \
|
53
|
+
if (little) \
|
54
|
+
MAKE_LOAD_LOOP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT ## _ ## le ); \
|
55
|
+
else \
|
56
|
+
MAKE_LOAD_LOOP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT ## _ ## be ); \
|
57
|
+
} while (0)
|
58
|
+
|
59
|
+
#define MAKE_LOAD(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT) \
|
60
|
+
MAKE_LOAD_LOOP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT)
|
61
|
+
|
62
|
+
/* load(input, input_big = LibBin::default_big?, parent = nil, index = nil, length = nil) */
|
63
|
+
#define MAKE_TYPE_LOAD(CLASS, MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT, LOAD) \
|
64
|
+
static VALUE CLASS ## _load(int argc, VALUE* argv, VALUE self) { \
|
65
|
+
(void)self; \
|
66
|
+
VALUE input; \
|
67
|
+
VALUE input_big; \
|
68
|
+
VALUE length; \
|
69
|
+
rb_scan_args(argc, argv, "14", &input, &input_big, NULL, NULL, &length); \
|
70
|
+
if (NIL_P(input_big)) \
|
71
|
+
input_big = rb_funcall(mLibBin, rb_intern("default_big?"), 0); \
|
72
|
+
unsigned little = RTEST(input_big) ? 0 : 1; \
|
73
|
+
long n = RTEST(length) ? NUM2LONG(length) : 1; \
|
74
|
+
size_t cnt = sizeof(MAPPED_TYPE) * n; \
|
75
|
+
VALUE res; \
|
76
|
+
VALUE str = rb_funcall(input, id_read, 1, ULL2NUM(cnt)); \
|
77
|
+
if (NIL_P(str) || RSTRING_LEN(str) < (long)cnt) \
|
78
|
+
rb_raise(rb_eRuntimeError, \
|
79
|
+
"could not read enough data: got %ld needed %zu", \
|
80
|
+
NIL_P(str) ? 0 : RSTRING_LEN(str), cnt); \
|
81
|
+
MAPPED_TYPE *data = (MAPPED_TYPE *)RSTRING_PTR(str); \
|
82
|
+
LOAD(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT); \
|
83
|
+
RB_GC_GUARD(str); \
|
84
|
+
return res; \
|
85
|
+
}
|
86
|
+
|
87
|
+
#define MAKE_DUMP_LOOP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT) \
|
88
|
+
do { \
|
89
|
+
if (RTEST(length)) \
|
90
|
+
for (long i = 0; i < n; i++) { \
|
91
|
+
MAPPED_TYPE v = NATIVE_CONVERT(RUBY_CONVERT(rb_ary_entry(value, i))); \
|
92
|
+
rb_str_cat(str, (char *)&v, sizeof(MAPPED_TYPE)); \
|
93
|
+
} \
|
94
|
+
else { \
|
95
|
+
MAPPED_TYPE v = NATIVE_CONVERT(RUBY_CONVERT(value)); \
|
96
|
+
rb_str_cat(str, (char *)&v, sizeof(MAPPED_TYPE)); \
|
97
|
+
} \
|
98
|
+
} while (0)
|
99
|
+
|
100
|
+
#define MAKE_DUMP_ENDIAN(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT) \
|
101
|
+
do { \
|
102
|
+
if (little) \
|
103
|
+
MAKE_DUMP_LOOP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT ## _ ## le ); \
|
104
|
+
else \
|
105
|
+
MAKE_DUMP_LOOP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT ## _ ## be ); \
|
106
|
+
} while (0)
|
107
|
+
|
108
|
+
#define MAKE_DUMP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT) \
|
109
|
+
MAKE_DUMP_LOOP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT)
|
110
|
+
|
111
|
+
/* dump(value, output, output_big = LibBin::default_big?, parent = nil, index = nil, length = nil) */
|
112
|
+
#define MAKE_TYPE_DUMP(CLASS, MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT, DUMP) \
|
113
|
+
static VALUE CLASS ## _dump(int argc, VALUE* argv, VALUE self) { \
|
114
|
+
(void)self; \
|
115
|
+
VALUE value; \
|
116
|
+
VALUE output; \
|
117
|
+
VALUE output_big; \
|
118
|
+
VALUE length; \
|
119
|
+
rb_scan_args(argc, argv, "24", &value, &output, &output_big, NULL, NULL, &length); \
|
120
|
+
if (NIL_P(output_big)) \
|
121
|
+
output_big = rb_funcall(mLibBin, rb_intern("default_big?"), 0); \
|
122
|
+
unsigned little = RTEST(output_big) ? 0 : 1; \
|
123
|
+
long n = RTEST(length) ? NUM2LONG(length) : 1; \
|
124
|
+
size_t cnt = sizeof(MAPPED_TYPE) * n; \
|
125
|
+
VALUE str = rb_str_buf_new((long)cnt); \
|
126
|
+
DUMP(MAPPED_TYPE, RUBY_CONVERT, NATIVE_CONVERT); \
|
127
|
+
rb_funcall(output, id_write, 1, str); \
|
128
|
+
return Qnil; \
|
129
|
+
}
|
130
|
+
|
131
|
+
#define MAKE_CONVERT_LOOP(MAPPED_TYPE, MAPPED_SWAP, SWAP_COND, RUBY_CONVERT, NATIVE_CONVERT) \
|
132
|
+
do { \
|
133
|
+
if (RTEST(length)) { \
|
134
|
+
res = rb_ary_new_capa(n); \
|
135
|
+
long i = 0; \
|
136
|
+
for (MAPPED_TYPE *p = data; p != data + n; p++, i++) { \
|
137
|
+
rb_ary_store(res, i, RUBY_CONVERT(NATIVE_CONVERT(*p))); \
|
138
|
+
if (SWAP_COND) \
|
139
|
+
*p = MAPPED_SWAP(*p); \
|
140
|
+
} \
|
141
|
+
} else { \
|
142
|
+
res = RUBY_CONVERT(NATIVE_CONVERT(*data)); \
|
143
|
+
if (SWAP_COND) \
|
144
|
+
*data = MAPPED_SWAP(*data); \
|
145
|
+
} \
|
146
|
+
} while(0)
|
147
|
+
|
148
|
+
#define MAKE_CONVERT_ENDIAN(MAPPED_TYPE, MAPPED_SWAP, RUBY_CONVERT, NATIVE_CONVERT) \
|
149
|
+
do { \
|
150
|
+
if (little_input) \
|
151
|
+
MAKE_CONVERT_LOOP(MAPPED_TYPE, MAPPED_SWAP, !little_output, RUBY_CONVERT, NATIVE_CONVERT ## _ ## le ); \
|
152
|
+
else \
|
153
|
+
MAKE_CONVERT_LOOP(MAPPED_TYPE, MAPPED_SWAP, little_output, RUBY_CONVERT, NATIVE_CONVERT ## _ ## be ); \
|
154
|
+
} while (0)
|
155
|
+
|
156
|
+
#define MAKE_CONVERT(MAPPED_TYPE, MAPPED_SWAP, RUBY_CONVERT, NATIVE_CONVERT) \
|
157
|
+
MAKE_CONVERT_LOOP(MAPPED_TYPE, MAPPED_SWAP, 0, RUBY_CONVERT, NATIVE_CONVERT)
|
158
|
+
|
159
|
+
|
160
|
+
/* convert(input, output, input_big = LibBin::default_big?, output_big = !input_big, parent = nil, index = nil, length = nil) */
|
161
|
+
#define MAKE_TYPE_CONVERT(CLASS, MAPPED_TYPE, MAPPED_SWAP, RUBY_CONVERT, NATIVE_CONVERT, CONVERT) \
|
162
|
+
static VALUE CLASS ## _convert(int argc, VALUE* argv, VALUE self) { \
|
163
|
+
(void)self; \
|
164
|
+
VALUE input; \
|
165
|
+
VALUE output; \
|
166
|
+
VALUE input_big; \
|
167
|
+
VALUE output_big; \
|
168
|
+
VALUE length; \
|
169
|
+
rb_scan_args(argc, argv, "25", &input, &output, &input_big, &output_big, NULL, NULL, &length); \
|
170
|
+
if (NIL_P(input_big)) \
|
171
|
+
input_big = rb_funcall(mLibBin, rb_intern("default_big?"), 0); \
|
172
|
+
unsigned little_input = RTEST(input_big) ? 0 : 1; \
|
173
|
+
if (NIL_P(output_big)) \
|
174
|
+
output_big = little_input ? Qtrue : Qfalse; \
|
175
|
+
unsigned little_output = RTEST(output_big) ? 0 : 1; \
|
176
|
+
long n = RTEST(length) ? NUM2LONG(length) : 1; \
|
177
|
+
size_t cnt = sizeof(MAPPED_TYPE) * n; \
|
178
|
+
VALUE res; \
|
179
|
+
VALUE str = rb_funcall(input, id_read, 1, ULL2NUM(cnt)); \
|
180
|
+
if (NIL_P(str) || RSTRING_LEN(str) < (long)cnt) \
|
181
|
+
rb_raise(rb_eRuntimeError, "could not read enough data: got %ld needed %zu", \
|
182
|
+
NIL_P(str) ? 0 : RSTRING_LEN(str), cnt); \
|
183
|
+
MAPPED_TYPE *data = (MAPPED_TYPE *)RSTRING_PTR(str); \
|
184
|
+
CONVERT(MAPPED_TYPE, MAPPED_SWAP, RUBY_CONVERT, NATIVE_CONVERT); \
|
185
|
+
rb_funcall(output, id_write, 1, str); \
|
186
|
+
return res; \
|
187
|
+
}
|
188
|
+
|
189
|
+
#define MAKE_CLASS_DEFINE(CLASS_NAME, CLASS) \
|
190
|
+
static void define_ ## CLASS() { \
|
191
|
+
CLASS = rb_define_class_under(cDataConverter, #CLASS_NAME, cScalar); \
|
192
|
+
rb_define_singleton_method(CLASS, "size", CLASS ## _size, -1); \
|
193
|
+
rb_define_singleton_method(CLASS, "shape", CLASS ## _shape, -1); \
|
194
|
+
rb_define_singleton_method(CLASS, "load", CLASS ## _load, -1); \
|
195
|
+
rb_define_singleton_method(CLASS, "dump", CLASS ## _dump, -1); \
|
196
|
+
rb_define_singleton_method(CLASS, "convert", CLASS ## _convert, -1); \
|
197
|
+
}
|
198
|
+
|
199
|
+
#define MAKE_STATIC_OBJECT(CLASS) \
|
200
|
+
static VALUE CLASS;
|
201
|
+
|
202
|
+
#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) \
|
203
|
+
MAKE_STATIC_OBJECT(CLASS) \
|
204
|
+
MAKE_TYPE_SIZE(CLASS, MAPPED_TYPE) \
|
205
|
+
MAKE_TYPE_SHAPE(CLASS, MAPPED_TYPE) \
|
206
|
+
MAKE_TYPE_LOAD(CLASS, MAPPED_TYPE, RUBY_CONVERT_TO, NATIVE_CONVERT_TO, MAKE_LOAD ## ENDIAN) \
|
207
|
+
MAKE_TYPE_DUMP(CLASS, MAPPED_TYPE, RUBY_CONVERT_FROM, NATIVE_CONVERT_FROM, MAKE_DUMP ## ENDIAN) \
|
208
|
+
MAKE_TYPE_CONVERT(CLASS, MAPPED_TYPE, MAPPED_SWAP, RUBY_CONVERT_TO, NATIVE_CONVERT_TO, MAKE_CONVERT ## ENDIAN) \
|
209
|
+
MAKE_CLASS_DEFINE(CLASS_NAME, CLASS)
|
210
|
+
|
211
|
+
#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) \
|
212
|
+
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)
|
213
|
+
|
214
|
+
#define ENDIAN_little
|
215
|
+
#define ENDIAN_big
|
216
|
+
#define ENDIAN_nil _ENDIAN
|
217
|
+
#define ENDIAN_suffix_little _le
|
218
|
+
#define ENDIAN_suffix_big _be
|
219
|
+
#define ENDIAN_suffix_nil
|
220
|
+
#define ENDIAN_SUFFIX_little _LE
|
221
|
+
#define ENDIAN_SUFFIX_big _BE
|
222
|
+
#define ENDIAN_SUFFIX_nil
|
223
|
+
|
224
|
+
#define MAKE_ENDIAN(ENDIAN) ENDIAN_ ## ENDIAN
|
225
|
+
#define MAKE_ENDIAN_suffix(ENDIAN) ENDIAN_suffix_ ## ENDIAN
|
226
|
+
#define MAKE_ENDIAN_SUFFIX(ENDIAN) ENDIAN_SUFFIX_ ## ENDIAN
|
227
|
+
#define MAKE_CONVERT_NAME_SUFFIX_EX(NAME, SUFFIX) NAME ## SUFFIX
|
228
|
+
#define MAKE_CONVERT_NAME_SUFFIX(NAME, SUFFIX) MAKE_CONVERT_NAME_SUFFIX_EX(NAME, SUFFIX)
|
229
|
+
#define MAKE_CONVERT_NAME_MAKE_SUFFIX(NAME, ENDIAN, MAKE_SUFFIX) MAKE_CONVERT_NAME_SUFFIX(NAME, MAKE_SUFFIX(ENDIAN))
|
230
|
+
#define MAKE_CLASS_NAME(CLASS_NAME, ENDIAN) MAKE_CONVERT_NAME_MAKE_SUFFIX(CLASS_NAME, ENDIAN, MAKE_ENDIAN_SUFFIX)
|
231
|
+
#define MAKE_C_CLASS_NAME(CLASS_NAME, ENDIAN) MAKE_CONVERT_NAME_MAKE_SUFFIX(c ## CLASS_NAME, ENDIAN, MAKE_ENDIAN_SUFFIX)
|
232
|
+
#define MAKE_CONVERT_NAME(NAME, ENDIAN) MAKE_CONVERT_NAME_MAKE_SUFFIX(NAME, ENDIAN, MAKE_ENDIAN_suffix)
|
233
|
+
|
234
|
+
#define MAKE_CLASS(CLASS_NAME, SIZE, RUBY_CONVERT_TO, RUBY_CONVERT_FROM, NATIVE_CONVERT_TO, NATIVE_CONVERT_FROM, ENDIAN) \
|
235
|
+
MAKE_CLASS_TYPE_ENDIAN(MAKE_CLASS_NAME(CLASS_NAME, ENDIAN), \
|
236
|
+
MAKE_C_CLASS_NAME(CLASS_NAME, ENDIAN), \
|
237
|
+
uint ## SIZE ## _t, \
|
238
|
+
bswap_uint ## SIZE, \
|
239
|
+
RUBY_CONVERT_TO, \
|
240
|
+
RUBY_CONVERT_FROM, \
|
241
|
+
MAKE_CONVERT_NAME(NATIVE_CONVERT_TO, ENDIAN), \
|
242
|
+
MAKE_CONVERT_NAME(NATIVE_CONVERT_FROM, ENDIAN), \
|
243
|
+
MAKE_ENDIAN(ENDIAN))
|
244
|
+
|
245
|
+
#define MAKE_CLASSES(CLASS_NAME, SIZE, RUBY_CONVERT_TO, RUBY_CONVERT_FROM, NATIVE_CONVERT_TO, NATIVE_CONVERT_FROM) \
|
246
|
+
MAKE_CLASS(CLASS_NAME, SIZE, RUBY_CONVERT_TO, RUBY_CONVERT_FROM, NATIVE_CONVERT_TO, NATIVE_CONVERT_FROM, nil) \
|
247
|
+
MAKE_CLASS(CLASS_NAME, SIZE, RUBY_CONVERT_TO, RUBY_CONVERT_FROM, NATIVE_CONVERT_TO, NATIVE_CONVERT_FROM, little) \
|
248
|
+
MAKE_CLASS(CLASS_NAME, SIZE, RUBY_CONVERT_TO, RUBY_CONVERT_FROM, NATIVE_CONVERT_TO, NATIVE_CONVERT_FROM, big)
|
249
|
+
|
250
|
+
#define MAKE_CALL_DEFINE(CLASS_NAME) \
|
251
|
+
do { \
|
252
|
+
define_ ## CLASS_NAME(); \
|
253
|
+
} while (0)
|
254
|
+
|
255
|
+
#define MAKE_CALL_DEFINE_EX(CLASS_NAME) \
|
256
|
+
MAKE_CALL_DEFINE(CLASS_NAME)
|
257
|
+
|
258
|
+
#define MAKE_CALL_DEFINES(CLASS_NAME) \
|
259
|
+
do { \
|
260
|
+
MAKE_CALL_DEFINE_EX(MAKE_C_CLASS_NAME(CLASS_NAME, nil)); \
|
261
|
+
MAKE_CALL_DEFINE_EX(MAKE_C_CLASS_NAME(CLASS_NAME, little)); \
|
262
|
+
MAKE_CALL_DEFINE_EX(MAKE_C_CLASS_NAME(CLASS_NAME, big)); \
|
263
|
+
} while (0)
|
264
|
+
|
265
|
+
static inline float half_to_float_le(uint16_t val) {
|
266
|
+
val = unpack_half_le(val);
|
267
|
+
union float_u u;
|
268
|
+
u.i = half_to_float(val);
|
269
|
+
return u.f;
|
270
|
+
}
|
271
|
+
|
272
|
+
static inline float half_to_float_be(uint16_t val) {
|
273
|
+
val = unpack_half_be(val);
|
274
|
+
union float_u u;
|
275
|
+
u.i = half_to_float(val);
|
276
|
+
return u.f;
|
277
|
+
}
|
278
|
+
|
279
|
+
static inline uint16_t float_to_half_le(float f) {
|
280
|
+
uint16_t res;
|
281
|
+
union float_u u;
|
282
|
+
u.f = f;
|
283
|
+
res = half_from_float(u.i);
|
284
|
+
res = pack_half_le(res);
|
285
|
+
return res;
|
286
|
+
}
|
287
|
+
|
288
|
+
static inline uint16_t float_to_half_be(float f) {
|
289
|
+
uint16_t res;
|
290
|
+
union float_u u;
|
291
|
+
u.f = f;
|
292
|
+
res = half_from_float(u.i);
|
293
|
+
res = pack_half_be(res);
|
294
|
+
return res;
|
295
|
+
}
|
296
|
+
|
297
|
+
|
298
|
+
MAKE_CLASSES(Half, 16, DBL2NUM, NUM2DBL, half_to_float, float_to_half)
|
299
|
+
|
300
|
+
static inline float pghalf_to_float_le(uint16_t val) {
|
301
|
+
val = unpack_pghalf_le(val);
|
302
|
+
union float_u u;
|
303
|
+
u.i = pghalf_to_float(val);
|
304
|
+
return u.f;
|
305
|
+
}
|
306
|
+
|
307
|
+
static inline float pghalf_to_float_be(uint16_t val) {
|
308
|
+
val = unpack_pghalf_be(val);
|
309
|
+
union float_u u;
|
310
|
+
u.i = pghalf_to_float(val);
|
311
|
+
return u.f;
|
312
|
+
}
|
313
|
+
|
314
|
+
static inline uint16_t float_to_pghalf_le(float f) {
|
315
|
+
uint16_t res;
|
316
|
+
union float_u u;
|
317
|
+
u.f = f;
|
318
|
+
res = pghalf_from_float(u.i);
|
319
|
+
res = pack_pghalf_le(res);
|
320
|
+
return res;
|
321
|
+
}
|
322
|
+
|
323
|
+
static inline uint16_t float_to_pghalf_be(float f) {
|
324
|
+
uint16_t res;
|
325
|
+
union float_u u;
|
326
|
+
u.f = f;
|
327
|
+
res = pghalf_from_float(u.i);
|
328
|
+
res = pack_pghalf_be(res);
|
329
|
+
return res;
|
330
|
+
}
|
331
|
+
|
332
|
+
MAKE_CLASSES(PGHalf, 16, DBL2NUM, NUM2DBL, pghalf_to_float, float_to_pghalf)
|
333
|
+
|
334
|
+
MAKE_CLASSES(Int8, 8, INT2FIX, NUM2SHORT, unpack_int8, pack_int8)
|
335
|
+
MAKE_CLASSES(UInt8, 8, USHORT2NUM, NUM2USHORT, unpack_uint8, pack_uint8)
|
336
|
+
MAKE_CLASSES(Int16, 16, INT2FIX, NUM2SHORT, unpack_int16, pack_int16)
|
337
|
+
MAKE_CLASSES(UInt16, 16, USHORT2NUM, NUM2USHORT, unpack_uint16, pack_uint16)
|
338
|
+
MAKE_CLASSES(Int32, 32, INT2NUM, NUM2INT, unpack_int32, pack_int32)
|
339
|
+
MAKE_CLASSES(UInt32, 32, UINT2NUM, NUM2UINT, unpack_uint32, pack_uint32)
|
340
|
+
MAKE_CLASSES(Int64, 64, LL2NUM, NUM2LL, unpack_int64, pack_int64)
|
341
|
+
MAKE_CLASSES(UInt64, 64, ULL2NUM, NUM2ULL, unpack_uint64, pack_uint64)
|
342
|
+
MAKE_CLASSES(Flt, 32, DBL2NUM, NUM2DBL, unpack_float, pack_float)
|
343
|
+
MAKE_CLASSES(Double, 64, DBL2NUM, NUM2DBL, unpack_double, pack_double)
|
344
|
+
|
345
|
+
static VALUE cStr;
|
346
|
+
|
347
|
+
static VALUE cStr_size(int argc, VALUE* argv, VALUE self) {
|
348
|
+
(void)self;
|
349
|
+
VALUE value;
|
350
|
+
VALUE length;
|
351
|
+
rb_scan_args(argc, argv, "14", &value, NULL, NULL, NULL, &length);
|
352
|
+
if (RTEST(length))
|
353
|
+
return length;
|
354
|
+
else
|
355
|
+
return rb_funcall(value, rb_intern("bytesize"), 0);
|
356
|
+
}
|
357
|
+
|
358
|
+
static VALUE cStr_shape(int argc, VALUE* argv, VALUE self) {
|
359
|
+
(void)self;
|
360
|
+
VALUE value;
|
361
|
+
VALUE previous_offset;
|
362
|
+
VALUE kind;
|
363
|
+
VALUE length;
|
364
|
+
rb_scan_args(argc, argv, "15", &value, &previous_offset, NULL, NULL, &kind, &length);
|
365
|
+
if (NIL_P(previous_offset))
|
366
|
+
previous_offset = INT2FIX(0);
|
367
|
+
if (NIL_P(kind))
|
368
|
+
kind = cDataShape;
|
369
|
+
if (NIL_P(length)) {
|
370
|
+
VALUE args[] = { previous_offset, LL2NUM(NUM2LL(previous_offset) - 1 + RSTRING_LEN(value)) };
|
371
|
+
return rb_class_new_instance(2, args, kind);
|
372
|
+
} else {
|
373
|
+
VALUE args[] = { previous_offset, LL2NUM(NUM2LL(previous_offset) - 1 + NUM2LL(length)) };
|
374
|
+
return rb_class_new_instance(2, args, kind);
|
375
|
+
}
|
376
|
+
}
|
377
|
+
|
378
|
+
static VALUE cStr_load(int argc, VALUE* argv, VALUE self) {
|
379
|
+
(void)self;
|
380
|
+
VALUE input;
|
381
|
+
VALUE length;
|
382
|
+
rb_scan_args(argc, argv, "14", &input, NULL, NULL, NULL, &length);
|
383
|
+
if (NIL_P(length))
|
384
|
+
return rb_funcall(input, rb_intern("readline"), 1, rb_str_new_static("", 1));
|
385
|
+
else {
|
386
|
+
VALUE str = rb_funcall(input, id_read, 1, length);
|
387
|
+
if (NIL_P(str) || RSTRING_LEN(str) < NUM2LONG(length))
|
388
|
+
rb_raise(rb_eRuntimeError,
|
389
|
+
"could not read enough data: got %ld needed %zu", RSTRING_LEN(str), NUM2LONG(length));
|
390
|
+
return str;
|
391
|
+
}
|
392
|
+
}
|
393
|
+
|
394
|
+
static VALUE cStr_dump(int argc, VALUE* argv, VALUE self) {
|
395
|
+
(void)self;
|
396
|
+
VALUE value;
|
397
|
+
VALUE output;
|
398
|
+
VALUE length;
|
399
|
+
rb_scan_args(argc, argv, "24", &value, &output, NULL, NULL, NULL, &length);
|
400
|
+
if (NIL_P(length))
|
401
|
+
rb_funcall(output, id_write, 1, value);
|
402
|
+
else {
|
403
|
+
long l = NUM2LONG(length);
|
404
|
+
long vl = RSTRING_LEN(value);
|
405
|
+
VALUE str;
|
406
|
+
if (vl > l)
|
407
|
+
str = rb_str_new(RSTRING_PTR(value), l);
|
408
|
+
else {
|
409
|
+
str = rb_str_buf_new(l);
|
410
|
+
rb_str_cat(str, RSTRING_PTR(value), vl);
|
411
|
+
for (long i = 0; i < l - vl; i++)
|
412
|
+
rb_str_cat(str, "", 1);
|
413
|
+
}
|
414
|
+
rb_funcall(output, id_write, 1, str);
|
415
|
+
}
|
416
|
+
return Qnil;
|
417
|
+
}
|
418
|
+
|
419
|
+
static VALUE cStr_convert(int argc, VALUE* argv, VALUE self) {
|
420
|
+
(void)self;
|
421
|
+
VALUE input;
|
422
|
+
VALUE output;
|
423
|
+
VALUE length;
|
424
|
+
rb_scan_args(argc, argv, "25", &input, &output, NULL, NULL, NULL, NULL, &length);
|
425
|
+
VALUE str;
|
426
|
+
if (NIL_P(length))
|
427
|
+
str = rb_funcall(input, rb_intern("readline"), 1, rb_str_new_static("", 1));
|
428
|
+
else {
|
429
|
+
str = rb_funcall(input, id_read, 1, length);
|
430
|
+
if (NIL_P(str) || RSTRING_LEN(str) < NUM2LONG(length))
|
431
|
+
rb_raise(rb_eRuntimeError,
|
432
|
+
"could not read enough data: got %ld needed %zu", RSTRING_LEN(str), NUM2LONG(length));
|
433
|
+
}
|
434
|
+
rb_funcall(output, id_write, 1, str);
|
435
|
+
return str;
|
436
|
+
}
|
437
|
+
|
438
|
+
static void define_cStr() {
|
439
|
+
cStr = rb_define_class_under(cDataConverter, "Str", cScalar);
|
440
|
+
rb_define_singleton_method(cStr, "size", cStr_size, -1);
|
441
|
+
rb_define_singleton_method(cStr, "shape", cStr_shape, -1);
|
442
|
+
rb_define_singleton_method(cStr, "load", cStr_load, -1);
|
443
|
+
rb_define_singleton_method(cStr, "dump", cStr_dump, -1);
|
444
|
+
rb_define_singleton_method(cStr, "convert", cStr_convert, -1);
|
445
|
+
}
|
446
|
+
|
447
|
+
void define_cScalar() {
|
448
|
+
id_read = rb_intern("read");
|
449
|
+
id_write = rb_intern("write");
|
450
|
+
cScalar = rb_define_class_under(cDataConverter, "Scalar", rb_cObject);
|
451
|
+
MAKE_CALL_DEFINES(Half);
|
452
|
+
MAKE_CALL_DEFINES(PGHalf);
|
453
|
+
MAKE_CALL_DEFINES(Int8);
|
454
|
+
MAKE_CALL_DEFINES(UInt8);
|
455
|
+
MAKE_CALL_DEFINES(Int16);
|
456
|
+
MAKE_CALL_DEFINES(UInt16);
|
457
|
+
MAKE_CALL_DEFINES(Int32);
|
458
|
+
MAKE_CALL_DEFINES(UInt32);
|
459
|
+
MAKE_CALL_DEFINES(Int64);
|
460
|
+
MAKE_CALL_DEFINES(UInt64);
|
461
|
+
MAKE_CALL_DEFINES(Flt);
|
462
|
+
MAKE_CALL_DEFINES(Double);
|
463
|
+
define_cStr();
|
464
|
+
}
|
465
|
+
|
466
|
+
|