libbin 1.0.5 → 2.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 +4 -4
- data/ext/libbin/data_types.c +557 -0
- data/ext/libbin/data_types.h +16 -0
- data/ext/libbin/libbin_c.c +1916 -41
- data/ext/libbin/libbin_c.h +12 -0
- data/ext/libbin/libbin_endian.h +126 -0
- data/lib/libbin/data_types.rb +629 -398
- data/lib/libbin.rb +77 -355
- data/libbin.gemspec +2 -3
- metadata +8 -6
- data/lib/libbin/alignment.rb +0 -14
data/ext/libbin/libbin_c.c
CHANGED
@@ -1,65 +1,1940 @@
|
|
1
1
|
#include "ruby.h"
|
2
|
-
#include "./
|
3
|
-
#include "./pghalf.h"
|
2
|
+
#include "./libbin_c.h"
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
VALUE cField;
|
5
|
+
VALUE mLibBin;
|
6
|
+
VALUE cStructure;
|
7
|
+
|
8
|
+
static VALUE rb_str_dot_dot;
|
9
|
+
static VALUE rb_str___parent;
|
10
|
+
static VALUE rb_str_backslash;
|
11
|
+
static VALUE rb_str_dot;
|
12
|
+
|
13
|
+
struct cField_data {
|
14
|
+
VALUE name;
|
15
|
+
VALUE type;
|
16
|
+
VALUE length;
|
17
|
+
VALUE count;
|
18
|
+
VALUE offset;
|
19
|
+
VALUE sequence;
|
20
|
+
VALUE condition;
|
21
|
+
VALUE relative_offset;
|
22
|
+
VALUE align;
|
23
|
+
VALUE expect;
|
24
|
+
ID getter;
|
25
|
+
ID setter;
|
26
|
+
};
|
27
|
+
|
28
|
+
static void cField_mark(void* data) {
|
29
|
+
void *start = data;
|
30
|
+
void *end = &((struct cField_data*)data)->getter;
|
31
|
+
rb_gc_mark_locations((VALUE *)start, (VALUE *)end);
|
32
|
+
}
|
33
|
+
|
34
|
+
static size_t cField_size(const void* data) {
|
35
|
+
(void)data;
|
36
|
+
return sizeof(struct cField_data);
|
37
|
+
}
|
38
|
+
|
39
|
+
static const rb_data_type_t cField_type = {
|
40
|
+
.wrap_struct_name = "cField_data",
|
41
|
+
.function = {
|
42
|
+
.dmark = cField_mark,
|
43
|
+
.dfree = RUBY_DEFAULT_FREE,
|
44
|
+
.dsize = cField_size,
|
45
|
+
},
|
46
|
+
.data = NULL,
|
47
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
48
|
+
};
|
49
|
+
|
50
|
+
static VALUE cField_alloc(VALUE self) {
|
51
|
+
struct cField_data *data;
|
52
|
+
VALUE res = TypedData_Make_Struct(self, struct cField_data, &cField_type, data);
|
53
|
+
return res;
|
54
|
+
}
|
55
|
+
|
56
|
+
static ID id_gsub;
|
57
|
+
|
58
|
+
static inline VALUE cField_preprocess_expression(VALUE self, VALUE expression) {
|
59
|
+
if (T_STRING == TYPE(expression)) {
|
60
|
+
VALUE proc = rb_str_new_cstr("proc {");
|
61
|
+
rb_str_buf_append(proc, rb_funcall(rb_funcall(expression, id_gsub, 2, rb_str_dot_dot, rb_str___parent), id_gsub, 2, rb_str_backslash, rb_str_dot));
|
62
|
+
rb_str_cat_cstr(proc, "}");
|
63
|
+
return rb_obj_instance_eval(1, &proc, self);
|
64
|
+
} else
|
65
|
+
return expression;
|
66
|
+
}
|
67
|
+
|
68
|
+
static VALUE cField_initialize(
|
69
|
+
VALUE self,
|
70
|
+
VALUE name,
|
71
|
+
VALUE type,
|
72
|
+
VALUE length,
|
73
|
+
VALUE count,
|
74
|
+
VALUE offset,
|
75
|
+
VALUE sequence,
|
76
|
+
VALUE condition,
|
77
|
+
VALUE relative_offset,
|
78
|
+
VALUE align,
|
79
|
+
VALUE expect) {
|
80
|
+
VALUE tmp;
|
81
|
+
struct cField_data *data;
|
82
|
+
TypedData_Get_Struct(self, struct cField_data, &cField_type, data);
|
83
|
+
if (RTEST(align)) {
|
84
|
+
size_t a = NUM2LL(align);
|
85
|
+
if (a & (a-1))
|
86
|
+
rb_raise(rb_eRuntimeError, "alignment is not a power of 2: %zu", a);
|
87
|
+
}
|
88
|
+
data->name = name;
|
89
|
+
tmp = rb_str_dup(rb_obj_as_string(name));
|
90
|
+
data->getter = rb_intern_str(tmp);
|
91
|
+
data->setter = rb_intern_str(rb_str_cat(tmp, "=", 1));
|
92
|
+
data->type = cField_preprocess_expression(self, type);
|
93
|
+
data->length = cField_preprocess_expression(self, length);
|
94
|
+
data->count = cField_preprocess_expression(self, count);
|
95
|
+
data->offset = cField_preprocess_expression(self, offset);
|
96
|
+
data->sequence = sequence;
|
97
|
+
data->condition = cField_preprocess_expression(self, condition);
|
98
|
+
data->relative_offset = relative_offset;
|
99
|
+
data->align = align;
|
100
|
+
data->expect = expect;
|
101
|
+
return self;
|
102
|
+
}
|
103
|
+
|
104
|
+
#define FIELD_STATE_GETTER(propname) cField_get_ ## propname
|
105
|
+
|
106
|
+
#define CREATE_FIELD_STATE_GETTER(propname) \
|
107
|
+
static VALUE FIELD_STATE_GETTER(propname) (VALUE self) { \
|
108
|
+
struct cField_data *data; \
|
109
|
+
TypedData_Get_Struct(self, struct cField_data, &cField_type, data); \
|
110
|
+
return data->propname ; \
|
111
|
+
}
|
112
|
+
|
113
|
+
#define DEFINE_FIELD_STATE_GETTER(propname) \
|
114
|
+
rb_define_method(cField, #propname, FIELD_STATE_GETTER(propname), 0)
|
115
|
+
|
116
|
+
#define DEFINE_FIELD_STATE_GETTER_BOOL(propname) \
|
117
|
+
rb_define_method(cField, #propname "?", FIELD_STATE_GETTER(propname), 0)
|
118
|
+
|
119
|
+
CREATE_FIELD_STATE_GETTER(name)
|
120
|
+
CREATE_FIELD_STATE_GETTER(type)
|
121
|
+
CREATE_FIELD_STATE_GETTER(length)
|
122
|
+
CREATE_FIELD_STATE_GETTER(count)
|
123
|
+
CREATE_FIELD_STATE_GETTER(offset)
|
124
|
+
CREATE_FIELD_STATE_GETTER(sequence)
|
125
|
+
CREATE_FIELD_STATE_GETTER(condition)
|
126
|
+
CREATE_FIELD_STATE_GETTER(relative_offset)
|
127
|
+
CREATE_FIELD_STATE_GETTER(align)
|
128
|
+
CREATE_FIELD_STATE_GETTER(expect)
|
129
|
+
|
130
|
+
struct cStructure_data {
|
131
|
+
VALUE __input;
|
132
|
+
VALUE __output;
|
133
|
+
VALUE __input_big;
|
134
|
+
VALUE __output_big;
|
135
|
+
VALUE __parent;
|
136
|
+
VALUE __index;
|
137
|
+
VALUE __position;
|
138
|
+
VALUE __cur_position;
|
139
|
+
// field specific data
|
140
|
+
VALUE __offset;
|
141
|
+
VALUE __condition;
|
142
|
+
VALUE __type;
|
143
|
+
VALUE __length;
|
144
|
+
VALUE __count;
|
145
|
+
VALUE __iterator;
|
146
|
+
VALUE __value;
|
147
|
+
};
|
148
|
+
|
149
|
+
static void cStructure_mark(void* data) {
|
150
|
+
void *start = data;
|
151
|
+
void *end = (char *)data + sizeof(struct cStructure_data);
|
152
|
+
rb_gc_mark_locations((VALUE *)start, (VALUE *)end);
|
153
|
+
}
|
154
|
+
|
155
|
+
static size_t cStructure_size(const void* data) {
|
156
|
+
(void)data;
|
157
|
+
return sizeof(struct cStructure_data);
|
158
|
+
}
|
159
|
+
|
160
|
+
static const rb_data_type_t cStructure_type = {
|
161
|
+
.wrap_struct_name = "cStructure_data",
|
162
|
+
.function = {
|
163
|
+
.dmark = cStructure_mark,
|
164
|
+
.dfree = RUBY_DEFAULT_FREE,
|
165
|
+
.dsize = cStructure_size,
|
166
|
+
},
|
167
|
+
.data = NULL,
|
168
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
169
|
+
};
|
170
|
+
|
171
|
+
static VALUE cStructure_alloc(VALUE self) {
|
172
|
+
struct cStructure_data *data;
|
173
|
+
VALUE res = TypedData_Make_Struct(self, struct cStructure_data, &cStructure_type, data);
|
174
|
+
return res;
|
175
|
+
}
|
176
|
+
|
177
|
+
static VALUE cStructure_initialize(VALUE self) {
|
178
|
+
struct cStructure_data *data;
|
179
|
+
TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
|
180
|
+
data->__input = Qnil;
|
181
|
+
data->__output = Qnil;
|
182
|
+
data->__input_big = Qnil;
|
183
|
+
data->__output_big = Qnil;
|
184
|
+
data->__parent = Qnil;
|
185
|
+
data->__index = Qnil;
|
186
|
+
data->__position = Qnil;
|
187
|
+
data->__cur_position = Qnil;
|
188
|
+
data->__offset = Qnil;
|
189
|
+
data->__condition = Qnil;
|
190
|
+
data->__type = Qnil;
|
191
|
+
data->__length = Qnil;
|
192
|
+
data->__count = Qnil;
|
193
|
+
data->__iterator = Qnil;
|
194
|
+
return self;
|
195
|
+
}
|
196
|
+
|
197
|
+
#define STRUCT_STATE_GETTER(propname) cStructure_get_ ## propname
|
198
|
+
#define STRUCT_STATE_SETTER(propname) cStructure_set_ ## propname
|
199
|
+
|
200
|
+
#define CREATE_STRUCT_STATE_ACCESSORS(propname) \
|
201
|
+
static VALUE STRUCT_STATE_GETTER(propname) (VALUE self) { \
|
202
|
+
struct cStructure_data *data; \
|
203
|
+
TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data); \
|
204
|
+
return data->__ ## propname ; \
|
205
|
+
} \
|
206
|
+
static VALUE STRUCT_STATE_SETTER(propname) (VALUE self, VALUE propname) { \
|
207
|
+
struct cStructure_data *data; \
|
208
|
+
TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data); \
|
209
|
+
return data->__ ## propname = propname; \
|
210
|
+
}
|
211
|
+
|
212
|
+
#define DEFINE_STRUCT_STATE_ACCESSORS(propname) \
|
213
|
+
do { \
|
214
|
+
rb_define_method(cStructure, "__" #propname, STRUCT_STATE_GETTER(propname), 0); \
|
215
|
+
rb_define_method(cStructure, "__" #propname "=", STRUCT_STATE_SETTER(propname), 1); \
|
216
|
+
} while(0)
|
217
|
+
|
218
|
+
CREATE_STRUCT_STATE_ACCESSORS(parent)
|
219
|
+
CREATE_STRUCT_STATE_ACCESSORS(index)
|
220
|
+
CREATE_STRUCT_STATE_ACCESSORS(position)
|
221
|
+
CREATE_STRUCT_STATE_ACCESSORS(cur_position)
|
222
|
+
CREATE_STRUCT_STATE_ACCESSORS(input)
|
223
|
+
CREATE_STRUCT_STATE_ACCESSORS(output)
|
224
|
+
CREATE_STRUCT_STATE_ACCESSORS(input_big)
|
225
|
+
CREATE_STRUCT_STATE_ACCESSORS(output_big)
|
226
|
+
|
227
|
+
CREATE_STRUCT_STATE_ACCESSORS(offset)
|
228
|
+
CREATE_STRUCT_STATE_ACCESSORS(condition)
|
229
|
+
CREATE_STRUCT_STATE_ACCESSORS(type)
|
230
|
+
CREATE_STRUCT_STATE_ACCESSORS(length)
|
231
|
+
CREATE_STRUCT_STATE_ACCESSORS(count)
|
232
|
+
CREATE_STRUCT_STATE_ACCESSORS(iterator)
|
233
|
+
CREATE_STRUCT_STATE_ACCESSORS(value)
|
234
|
+
|
235
|
+
static ID id_tell;
|
236
|
+
|
237
|
+
static ID id___set_convert_state;
|
238
|
+
|
239
|
+
static VALUE cStructure_set_convert_state(
|
240
|
+
VALUE self,
|
241
|
+
VALUE input,
|
242
|
+
VALUE output,
|
243
|
+
VALUE input_big,
|
244
|
+
VALUE output_big,
|
245
|
+
VALUE parent,
|
246
|
+
VALUE index)
|
247
|
+
{
|
248
|
+
struct cStructure_data *data;
|
249
|
+
TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
|
250
|
+
data->__input = input;
|
251
|
+
data->__output = output;
|
252
|
+
data->__input_big = input_big;
|
253
|
+
data->__output_big = output_big;
|
254
|
+
data->__parent = parent;
|
255
|
+
data->__index = index;
|
256
|
+
data->__position = rb_funcall(input, id_tell, 0);
|
257
|
+
data->__cur_position = data->__position;
|
258
|
+
return Qnil;
|
259
|
+
}
|
260
|
+
|
261
|
+
static ID id___unset_convert_state;
|
262
|
+
|
263
|
+
static VALUE cStructure_unset_convert_state(VALUE self) {
|
264
|
+
struct cStructure_data *data;
|
265
|
+
TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
|
266
|
+
data->__input = Qnil;
|
267
|
+
data->__output = Qnil;
|
268
|
+
data->__input_big = Qnil;
|
269
|
+
data->__output_big = Qnil;
|
270
|
+
data->__parent = Qnil;
|
271
|
+
data->__index = Qnil;
|
272
|
+
data->__position = Qnil;
|
273
|
+
data->__cur_position = Qnil;
|
274
|
+
return Qnil;
|
275
|
+
}
|
276
|
+
|
277
|
+
static ID id___set_size_state;
|
278
|
+
|
279
|
+
static VALUE cStructure_set_size_state(
|
280
|
+
VALUE self,
|
281
|
+
VALUE position,
|
282
|
+
VALUE parent,
|
283
|
+
VALUE index)
|
284
|
+
{
|
285
|
+
struct cStructure_data *data;
|
286
|
+
TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
|
287
|
+
data->__parent = parent;
|
288
|
+
data->__index = index;
|
289
|
+
data->__position = position;
|
290
|
+
data->__cur_position = data->__position;
|
291
|
+
return Qnil;
|
292
|
+
}
|
293
|
+
|
294
|
+
static ID id___unset_size_state;
|
295
|
+
|
296
|
+
static VALUE cStructure_unset_size_state(VALUE self) {
|
297
|
+
struct cStructure_data *data;
|
298
|
+
TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
|
299
|
+
data->__parent = Qnil;
|
300
|
+
data->__index = Qnil;
|
301
|
+
data->__position = Qnil;
|
302
|
+
data->__cur_position = Qnil;
|
303
|
+
return Qnil;
|
304
|
+
}
|
305
|
+
|
306
|
+
static ID id___set_load_state;
|
307
|
+
|
308
|
+
static VALUE cStructure_set_load_state(
|
309
|
+
VALUE self,
|
310
|
+
VALUE input,
|
311
|
+
VALUE input_big,
|
312
|
+
VALUE parent,
|
313
|
+
VALUE index)
|
314
|
+
{
|
315
|
+
struct cStructure_data *data;
|
316
|
+
TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
|
317
|
+
data->__input = input;
|
318
|
+
data->__input_big = input_big;
|
319
|
+
data->__parent = parent;
|
320
|
+
data->__index = index;
|
321
|
+
data->__position = rb_funcall(input, id_tell, 0);
|
322
|
+
data->__cur_position = data->__position;
|
323
|
+
return Qnil;
|
324
|
+
}
|
325
|
+
|
326
|
+
static ID id___unset_load_state;
|
327
|
+
|
328
|
+
static VALUE cStructure_unset_load_state(VALUE self) {
|
329
|
+
struct cStructure_data *data;
|
330
|
+
TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
|
331
|
+
data->__input = Qnil;
|
332
|
+
data->__input_big = Qnil;
|
333
|
+
data->__parent = Qnil;
|
334
|
+
data->__index = Qnil;
|
335
|
+
data->__position = Qnil;
|
336
|
+
data->__cur_position = Qnil;
|
337
|
+
return Qnil;
|
338
|
+
}
|
339
|
+
|
340
|
+
static ID id___set_dump_state;
|
341
|
+
|
342
|
+
static VALUE cStructure_set_dump_state(
|
343
|
+
VALUE self,
|
344
|
+
VALUE output,
|
345
|
+
VALUE output_big,
|
346
|
+
VALUE parent,
|
347
|
+
VALUE index)
|
348
|
+
{
|
349
|
+
struct cStructure_data *data;
|
350
|
+
TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
|
351
|
+
data->__output = output;
|
352
|
+
data->__output_big = output_big;
|
353
|
+
data->__parent = parent;
|
354
|
+
data->__index = index;
|
355
|
+
data->__position = rb_funcall(output, id_tell, 0);
|
356
|
+
data->__cur_position = data->__position;
|
357
|
+
return Qnil;
|
358
|
+
}
|
359
|
+
|
360
|
+
static ID id___unset_dump_state;
|
361
|
+
|
362
|
+
static VALUE cStructure_unset_dump_state(VALUE self) {
|
363
|
+
struct cStructure_data *data;
|
364
|
+
TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
|
365
|
+
data->__output = Qnil;
|
366
|
+
data->__output_big = Qnil;
|
367
|
+
data->__parent = Qnil;
|
368
|
+
data->__index = Qnil;
|
369
|
+
data->__position = Qnil;
|
370
|
+
data->__cur_position = Qnil;
|
371
|
+
return Qnil;
|
372
|
+
}
|
373
|
+
|
374
|
+
static ID id_instance_exec;
|
375
|
+
|
376
|
+
static inline VALUE cStructure_decode_expression(VALUE self, VALUE expression) {
|
377
|
+
if (rb_obj_is_proc(expression))
|
378
|
+
return rb_funcall_with_block(self, id_instance_exec, 0, NULL, expression);
|
379
|
+
else
|
380
|
+
return expression;
|
381
|
+
}
|
382
|
+
|
383
|
+
static inline VALUE cStructure_decode_expect(VALUE self, VALUE expect, VALUE val) {
|
384
|
+
if (NIL_P(expect))
|
385
|
+
return val;
|
386
|
+
if (rb_obj_is_proc(expect)) {
|
387
|
+
if (!RTEST(rb_funcall_with_block(self, id_instance_exec, 1, &val, expect)))
|
388
|
+
rb_raise(rb_eRuntimeError, "could not validate field value: %"PRIsVALUE, val);
|
389
|
+
} else
|
390
|
+
if (!RTEST(rb_equal(expect, val)))
|
391
|
+
rb_raise(rb_eRuntimeError, "could not validate field value: %"PRIsVALUE" expected: %"PRIsVALUE, val, expect);
|
392
|
+
return val;
|
393
|
+
}
|
394
|
+
|
395
|
+
ID id_seek;
|
396
|
+
|
397
|
+
static inline VALUE cStructure_decode_seek_offset(VALUE self, VALUE offset, VALUE relative_offset, VALUE align) {
|
398
|
+
struct cStructure_data *data;
|
399
|
+
TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
|
400
|
+
ptrdiff_t cur_pos;
|
401
|
+
if (!RTEST(offset)) {
|
402
|
+
if (!RTEST(align))
|
403
|
+
return Qnil;
|
404
|
+
if (RTEST(data->__input))
|
405
|
+
cur_pos = NUM2LL(rb_funcall(data->__input, id_tell, 0));
|
406
|
+
else if (RTEST(data->__output))
|
407
|
+
cur_pos = NUM2LL(rb_funcall(data->__output, id_tell, 0));
|
408
|
+
else
|
409
|
+
cur_pos = NUM2LL(data->__cur_position);
|
410
|
+
ptrdiff_t al = NUM2LL(align);
|
411
|
+
ptrdiff_t pad;
|
412
|
+
if ((pad = ((-cur_pos) & (al - 1))) == 0)
|
413
|
+
return Qnil;
|
414
|
+
cur_pos += pad;
|
415
|
+
} else {
|
416
|
+
cur_pos = NUM2LL(cStructure_decode_expression(self, offset));
|
417
|
+
if (cur_pos == 0)
|
418
|
+
return Qfalse;
|
419
|
+
if (RTEST(relative_offset))
|
420
|
+
cur_pos += NUM2LL(data->__position);
|
421
|
+
if (RTEST(align)) {
|
422
|
+
ptrdiff_t al = NUM2LL(align);
|
423
|
+
cur_pos += (-cur_pos) & (al - 1);
|
424
|
+
}
|
425
|
+
}
|
426
|
+
data->__cur_position = LL2NUM(cur_pos);
|
427
|
+
if (RTEST(data->__input))
|
428
|
+
rb_funcall(data->__input, id_seek, 1, data->__cur_position);
|
429
|
+
if (RTEST(data->__output))
|
430
|
+
rb_funcall(data->__output, id_seek, 1, data->__cur_position);
|
431
|
+
return data->__cur_position;
|
432
|
+
}
|
433
|
+
|
434
|
+
static inline VALUE cStructure_decode_condition(VALUE self, VALUE condition) {
|
435
|
+
if (!RTEST(condition))
|
436
|
+
return Qtrue;
|
437
|
+
return cStructure_decode_expression(self, condition);
|
438
|
+
}
|
439
|
+
|
440
|
+
static inline VALUE cStructure_decode_count(VALUE self, VALUE count) {
|
441
|
+
if (!RTEST(count))
|
442
|
+
return INT2FIX(1);
|
443
|
+
return cStructure_decode_expression(self, count);
|
444
|
+
}
|
445
|
+
|
446
|
+
static inline VALUE cStructure_decode_type(VALUE self, VALUE type) {
|
447
|
+
return cStructure_decode_expression(self, type);
|
448
|
+
}
|
449
|
+
|
450
|
+
static inline VALUE cStructure_decode_length(VALUE self, VALUE length) {
|
451
|
+
if (NIL_P(length))
|
452
|
+
return Qnil;
|
453
|
+
return cStructure_decode_expression(self, length);
|
454
|
+
}
|
455
|
+
|
456
|
+
static inline VALUE cStructure_decode_static_conditions(VALUE self, VALUE field) {
|
457
|
+
struct cStructure_data *data;
|
458
|
+
struct cField_data *field_data;
|
459
|
+
TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
|
460
|
+
TypedData_Get_Struct(field, struct cField_data, &cField_type, field_data);
|
461
|
+
data->__offset = Qnil;
|
462
|
+
data->__condition = Qnil;
|
463
|
+
data->__type = Qnil;
|
464
|
+
data->__length = Qnil;
|
465
|
+
data->__count = Qnil;
|
466
|
+
if (!RTEST(field_data->sequence)) {
|
467
|
+
data->__offset = cStructure_decode_seek_offset(self, field_data->offset, field_data->relative_offset, field_data->align);
|
468
|
+
if (!data->__offset)
|
469
|
+
return Qnil;
|
470
|
+
data->__condition = cStructure_decode_condition(self, field_data->condition);
|
471
|
+
if (!RTEST(data->__condition))
|
472
|
+
return Qnil;
|
473
|
+
data->__type = cStructure_decode_type(self, field_data->type);
|
474
|
+
data->__length = cStructure_decode_length(self, field_data->length);
|
475
|
+
}
|
476
|
+
data->__count = cStructure_decode_count(self, field_data->count);
|
477
|
+
return Qtrue;
|
478
|
+
}
|
479
|
+
|
480
|
+
static inline VALUE cStructure_decode_dynamic_conditions(VALUE self, VALUE field) {
|
481
|
+
struct cStructure_data *data;
|
482
|
+
struct cField_data *field_data;
|
483
|
+
TypedData_Get_Struct(field, struct cField_data, &cField_type, field_data);
|
484
|
+
if (!RTEST(field_data->sequence))
|
485
|
+
return Qtrue;
|
486
|
+
TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
|
487
|
+
data->__offset = Qnil;
|
488
|
+
data->__condition = Qnil;
|
489
|
+
data->__type = Qnil;
|
490
|
+
data->__length = Qnil;
|
491
|
+
data->__offset = cStructure_decode_seek_offset(self, field_data->offset, field_data->relative_offset, field_data->align);
|
492
|
+
if (!data->__offset)
|
493
|
+
return Qfalse;
|
494
|
+
data->__condition = cStructure_decode_condition(self, field_data->condition);
|
495
|
+
if (!RTEST(data->__condition))
|
496
|
+
return Qfalse;
|
497
|
+
data->__type = cStructure_decode_type(self, field_data->type);
|
498
|
+
data->__length = cStructure_decode_length(self, field_data->length);
|
499
|
+
return Qtrue;
|
500
|
+
}
|
501
|
+
|
502
|
+
static inline VALUE cStructure_restore_context(VALUE self) {
|
503
|
+
struct cStructure_data *data;
|
504
|
+
TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
|
505
|
+
data->__iterator = Qnil;
|
506
|
+
data->__type = Qnil;
|
507
|
+
data->__length = Qnil;
|
508
|
+
data->__count = Qnil;
|
509
|
+
data->__offset = Qnil;
|
510
|
+
data->__condition = Qnil;
|
511
|
+
data->__value = Qnil;
|
512
|
+
return Qnil;
|
513
|
+
}
|
514
|
+
|
515
|
+
static ID id_convert;
|
516
|
+
static ID id___convert_field;
|
517
|
+
|
518
|
+
static inline VALUE cStructure_convert_field(VALUE self, VALUE field) {
|
519
|
+
VALUE res;
|
520
|
+
struct cStructure_data *data;
|
521
|
+
struct cField_data *field_data;
|
522
|
+
if (NIL_P(cStructure_decode_static_conditions(self, field)))
|
523
|
+
return Qnil;
|
524
|
+
TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
|
525
|
+
TypedData_Get_Struct(field, struct cField_data, &cField_type, field_data);
|
526
|
+
|
527
|
+
if (RTEST(field_data->count)) {
|
528
|
+
long count = NUM2LONG(data->__count);
|
529
|
+
res = rb_ary_new_capa(count);
|
530
|
+
|
531
|
+
for (long i = 0; i < count; i++) {
|
532
|
+
data->__iterator = LONG2NUM(i);
|
533
|
+
if (RTEST(cStructure_decode_dynamic_conditions(self, field))) {
|
534
|
+
data->__value = rb_funcall(data->__type, id_convert, 7,
|
535
|
+
data->__input,
|
536
|
+
data->__output,
|
537
|
+
data->__input_big,
|
538
|
+
data->__output_big,
|
539
|
+
self,
|
540
|
+
data->__iterator,
|
541
|
+
data->__length);
|
542
|
+
rb_ary_store(res, i,
|
543
|
+
cStructure_decode_expect(self, field_data->expect, data->__value));
|
544
|
+
} else
|
545
|
+
rb_ary_store(res, i, Qnil);
|
546
|
+
}
|
547
|
+
} else {
|
548
|
+
data->__iterator = INT2FIX(0);
|
549
|
+
if (RTEST(cStructure_decode_dynamic_conditions(self, field))) {
|
550
|
+
data->__value = rb_funcall(data->__type, id_convert, 7,
|
551
|
+
data->__input,
|
552
|
+
data->__output,
|
553
|
+
data->__input_big,
|
554
|
+
data->__output_big,
|
555
|
+
self,
|
556
|
+
data->__iterator,
|
557
|
+
data->__length);
|
558
|
+
res = cStructure_decode_expect(self, field_data->expect, data->__value);
|
559
|
+
} else
|
560
|
+
res = Qnil;
|
561
|
+
}
|
562
|
+
|
563
|
+
cStructure_restore_context(self);
|
564
|
+
return res;
|
565
|
+
}
|
566
|
+
|
567
|
+
static ID id_load;
|
568
|
+
static ID id___load_field;
|
569
|
+
|
570
|
+
static inline VALUE cStructure_load_field(VALUE self, VALUE field) {
|
571
|
+
VALUE res;
|
572
|
+
struct cStructure_data *data;
|
573
|
+
struct cField_data *field_data;
|
574
|
+
if (NIL_P(cStructure_decode_static_conditions(self, field)))
|
575
|
+
return Qnil;
|
576
|
+
TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
|
577
|
+
TypedData_Get_Struct(field, struct cField_data, &cField_type, field_data);
|
578
|
+
|
579
|
+
if (RTEST(field_data->count)) {
|
580
|
+
long count = NUM2LONG(data->__count);
|
581
|
+
res = rb_ary_new_capa(count);
|
582
|
+
|
583
|
+
for (long i = 0; i < count; i++) {
|
584
|
+
data->__iterator = LONG2NUM(i);
|
585
|
+
if (RTEST(cStructure_decode_dynamic_conditions(self, field))) {
|
586
|
+
data->__value = rb_funcall(data->__type, id_load, 5,
|
587
|
+
data->__input,
|
588
|
+
data->__input_big,
|
589
|
+
self,
|
590
|
+
data->__iterator,
|
591
|
+
data->__length);
|
592
|
+
rb_ary_store(res, i,
|
593
|
+
cStructure_decode_expect(self, field_data->expect, data->__value));
|
594
|
+
} else
|
595
|
+
rb_ary_store(res, i, Qnil);
|
596
|
+
}
|
597
|
+
} else {
|
598
|
+
data->__iterator = INT2FIX(0);
|
599
|
+
if (RTEST(cStructure_decode_dynamic_conditions(self, field))) {
|
600
|
+
data->__value = rb_funcall(data->__type, id_load, 5,
|
601
|
+
data->__input,
|
602
|
+
data->__input_big,
|
603
|
+
self,
|
604
|
+
data->__iterator,
|
605
|
+
data->__length);
|
606
|
+
res = cStructure_decode_expect(self, field_data->expect, data->__value);
|
607
|
+
} else
|
608
|
+
res = Qnil;
|
609
|
+
}
|
610
|
+
cStructure_restore_context(self);
|
611
|
+
return res;
|
612
|
+
}
|
613
|
+
|
614
|
+
static ID id_dump;
|
615
|
+
static ID id___dump_field;
|
616
|
+
|
617
|
+
static inline VALUE cStructure_dump_field(VALUE self, VALUE values, VALUE field) {
|
618
|
+
struct cStructure_data *data;
|
619
|
+
struct cField_data *field_data;
|
620
|
+
if (NIL_P(cStructure_decode_static_conditions(self, field)))
|
621
|
+
return Qnil;
|
622
|
+
TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
|
623
|
+
TypedData_Get_Struct(field, struct cField_data, &cField_type, field_data);
|
624
|
+
|
625
|
+
if (RTEST(field_data->count)) {
|
626
|
+
long count = RARRAY_LEN(values);
|
627
|
+
|
628
|
+
for (long i = 0; i < count; i++) {
|
629
|
+
data->__iterator = LONG2NUM(i);
|
630
|
+
if (RTEST(cStructure_decode_dynamic_conditions(self, field))) {
|
631
|
+
data->__value = rb_ary_entry(values, i);
|
632
|
+
cStructure_decode_expect(self, field_data->expect, data->__value);
|
633
|
+
rb_funcall(data->__type, id_dump, 6,
|
634
|
+
data->__value,
|
635
|
+
data->__output,
|
636
|
+
data->__output_big,
|
637
|
+
self,
|
638
|
+
data->__iterator,
|
639
|
+
data->__length);
|
640
|
+
}
|
641
|
+
}
|
642
|
+
} else {
|
643
|
+
data->__iterator = INT2FIX(0);
|
644
|
+
if (RTEST(cStructure_decode_dynamic_conditions(self, field))) {
|
645
|
+
data->__value = values;
|
646
|
+
cStructure_decode_expect(self, field_data->expect, data->__value);
|
647
|
+
rb_funcall(data->__type, id_dump, 6,
|
648
|
+
data->__value,
|
649
|
+
data->__output,
|
650
|
+
data->__output_big,
|
651
|
+
self,
|
652
|
+
data->__iterator,
|
653
|
+
data->__length);
|
654
|
+
}
|
655
|
+
}
|
656
|
+
cStructure_restore_context(self);
|
657
|
+
return Qnil;
|
658
|
+
}
|
659
|
+
|
660
|
+
static ID id_shape;
|
661
|
+
static ID id___shape_field;
|
662
|
+
|
663
|
+
static inline VALUE cStructure_shape_field(
|
664
|
+
VALUE self,
|
665
|
+
VALUE values,
|
666
|
+
VALUE kind,
|
667
|
+
VALUE field)
|
668
|
+
{
|
669
|
+
VALUE res = Qnil;
|
670
|
+
struct cStructure_data *data;
|
671
|
+
struct cField_data *field_data;
|
672
|
+
if (NIL_P(cStructure_decode_static_conditions(self, field)))
|
673
|
+
return Qnil;
|
674
|
+
TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
|
675
|
+
TypedData_Get_Struct(field, struct cField_data, &cField_type, field_data);
|
676
|
+
|
677
|
+
if (RTEST(field_data->count)) {
|
678
|
+
long count = RARRAY_LEN(values);
|
679
|
+
res = rb_ary_new_capa(count);
|
680
|
+
|
681
|
+
for (long i = 0; i < count; i++) {
|
682
|
+
data->__iterator = LONG2NUM(i);
|
683
|
+
if (RTEST(cStructure_decode_dynamic_conditions(self, field))) {
|
684
|
+
VALUE shape = rb_funcall(data->__type, id_shape, 6,
|
685
|
+
rb_ary_entry(values, i),
|
686
|
+
data->__cur_position,
|
687
|
+
self,
|
688
|
+
data->__iterator,
|
689
|
+
kind,
|
690
|
+
data->__length);
|
691
|
+
rb_ary_store(res, i, shape);
|
692
|
+
VALUE last = rb_funcall(shape, rb_intern("last"), 0);
|
693
|
+
if (RTEST(last)) {
|
694
|
+
ptrdiff_t pos = NUM2LL(last);
|
695
|
+
if (pos >= 0)
|
696
|
+
data->__cur_position = LL2NUM(pos + 1);
|
697
|
+
}
|
698
|
+
}
|
699
|
+
}
|
700
|
+
res = rb_class_new_instance(1, &res, kind);
|
701
|
+
} else {
|
702
|
+
data->__iterator = INT2FIX(0);
|
703
|
+
if (RTEST(cStructure_decode_dynamic_conditions(self, field))) {
|
704
|
+
res = rb_funcall(data->__type, id_shape, 6,
|
705
|
+
values,
|
706
|
+
data->__cur_position,
|
707
|
+
self,
|
708
|
+
data->__iterator,
|
709
|
+
kind,
|
710
|
+
data->__length);
|
711
|
+
VALUE last = rb_funcall(res, rb_intern("last"), 0);
|
712
|
+
if (RTEST(last)) {
|
713
|
+
ptrdiff_t pos = NUM2LL(last);
|
714
|
+
if (pos >= 0)
|
715
|
+
data->__cur_position = LL2NUM(pos + 1);
|
716
|
+
}
|
717
|
+
}
|
718
|
+
}
|
719
|
+
cStructure_restore_context(self);
|
720
|
+
return res;
|
721
|
+
}
|
722
|
+
|
723
|
+
static ID id_fields;
|
724
|
+
|
725
|
+
struct fields_state {
|
726
|
+
VALUE self;
|
727
|
+
VALUE fields;
|
728
|
+
VALUE field;
|
729
|
+
};
|
730
|
+
|
731
|
+
static inline VALUE cStructure_fields_rescue(VALUE state_p, VALUE exception) {
|
732
|
+
struct fields_state *state = (struct fields_state *)state_p;
|
733
|
+
if (NIL_P(state->field)) {
|
734
|
+
struct cStructure_data *data;
|
735
|
+
TypedData_Get_Struct(state->self, struct cStructure_data, &cStructure_type, data);
|
736
|
+
if (!NIL_P(rb_funcall(mLibBin, rb_intern("output"), 0)))
|
737
|
+
rb_funcall(rb_funcall(mLibBin, rb_intern("output"), 0), rb_intern("print"), 6,
|
738
|
+
rb_obj_class(state->self),
|
739
|
+
rb_str_new_cstr(": could not load fields, index: "),
|
740
|
+
data->__index,
|
741
|
+
rb_str_new_cstr(", current position: "),
|
742
|
+
data->__cur_position,
|
743
|
+
rb_str_new_cstr("\n"));
|
744
|
+
} else {
|
745
|
+
struct cField_data *field_data;
|
746
|
+
TypedData_Get_Struct(state->field, struct cField_data, &cField_type, field_data);
|
747
|
+
if (!NIL_P(rb_funcall(mLibBin, rb_intern("output"), 0)))
|
748
|
+
rb_funcall(rb_funcall(mLibBin, rb_intern("output"), 0), rb_intern("print"), 6,
|
749
|
+
rb_obj_class(state->self),
|
750
|
+
rb_str_new_cstr(": "),
|
751
|
+
field_data->name,
|
752
|
+
rb_str_new_cstr("("),
|
753
|
+
field_data->type,
|
754
|
+
rb_str_new_cstr(")\n"));
|
755
|
+
}
|
756
|
+
rb_exc_raise(exception);
|
757
|
+
return state->self;
|
758
|
+
}
|
759
|
+
|
760
|
+
static inline VALUE cStructure_load_fields_wrapper(VALUE state_p) {
|
761
|
+
struct fields_state *state = (struct fields_state *)state_p;
|
762
|
+
state->fields = rb_ivar_get(rb_obj_class(state->self), id_fields);
|
763
|
+
for (long i = 0; i < RARRAY_LEN(state->fields); i++) {
|
764
|
+
state->field = rb_ary_entry(state->fields, i);
|
765
|
+
struct cField_data *field_data;
|
766
|
+
TypedData_Get_Struct(state->field, struct cField_data, &cField_type, field_data);
|
767
|
+
rb_funcall(state->self, field_data->setter, 1, rb_funcall(state->self, id___load_field, 1, state->field));
|
768
|
+
}
|
769
|
+
return state->self;
|
770
|
+
}
|
771
|
+
|
772
|
+
static ID id___load_fields;
|
773
|
+
|
774
|
+
static VALUE cStructure_load_fields(VALUE self) {
|
775
|
+
struct fields_state state = {self, Qnil, Qnil};
|
776
|
+
rb_rescue(&cStructure_load_fields_wrapper, (VALUE)&state,
|
777
|
+
&cStructure_fields_rescue, (VALUE)&state);
|
778
|
+
return self;
|
779
|
+
}
|
780
|
+
|
781
|
+
static inline VALUE cStructure_dump_fields_wrapper(VALUE state_p) {
|
782
|
+
struct fields_state *state = (struct fields_state *)state_p;
|
783
|
+
state->fields = rb_ivar_get(rb_obj_class(state->self), id_fields);
|
784
|
+
for (long i = 0; i < RARRAY_LEN(state->fields); i++) {
|
785
|
+
state->field = rb_ary_entry(state->fields, i);
|
786
|
+
struct cField_data *field_data;
|
787
|
+
TypedData_Get_Struct(state->field, struct cField_data, &cField_type, field_data);
|
788
|
+
rb_funcall(state->self, id___dump_field, 2, rb_funcall(state->self, field_data->getter, 0), state->field);
|
789
|
+
}
|
790
|
+
return state->self;
|
791
|
+
}
|
792
|
+
|
793
|
+
static ID id___dump_fields;
|
794
|
+
|
795
|
+
static VALUE cStructure_dump_fields(VALUE self) {
|
796
|
+
struct fields_state state = {self, Qnil, Qnil};
|
797
|
+
rb_rescue(&cStructure_dump_fields_wrapper, (VALUE)&state,
|
798
|
+
&cStructure_fields_rescue, (VALUE)&state);
|
799
|
+
return self;
|
800
|
+
}
|
801
|
+
|
802
|
+
static inline VALUE cStructure_convert_fields_wrapper(VALUE state_p) {
|
803
|
+
struct fields_state *state = (struct fields_state *)state_p;
|
804
|
+
state->fields = rb_ivar_get(rb_obj_class(state->self), id_fields);
|
805
|
+
for (long i = 0; i < RARRAY_LEN(state->fields); i++) {
|
806
|
+
state->field = rb_ary_entry(state->fields, i);
|
807
|
+
struct cField_data *field_data;
|
808
|
+
TypedData_Get_Struct(state->field, struct cField_data, &cField_type, field_data);
|
809
|
+
rb_funcall(state->self, field_data->setter, 1, rb_funcall(state->self, id___convert_field, 1, state->field));
|
810
|
+
}
|
811
|
+
return state->self;
|
812
|
+
}
|
813
|
+
|
814
|
+
static ID id___convert_fields;
|
815
|
+
|
816
|
+
static VALUE cStructure_convert_fields(VALUE self) {
|
817
|
+
struct fields_state state = {self, Qnil, Qnil};
|
818
|
+
rb_rescue(&cStructure_convert_fields_wrapper, (VALUE)&state,
|
819
|
+
&cStructure_fields_rescue, (VALUE)&state);
|
820
|
+
return self;
|
821
|
+
}
|
822
|
+
|
823
|
+
struct shape_fields_state {
|
824
|
+
VALUE self;
|
825
|
+
VALUE fields;
|
826
|
+
VALUE field;
|
827
|
+
VALUE kind;
|
8
828
|
};
|
9
829
|
|
830
|
+
static inline VALUE cStructure_shape_fields_wrapper(VALUE state_p) {
|
831
|
+
struct shape_fields_state *state = (struct shape_fields_state *)state_p;
|
832
|
+
state->fields = rb_ivar_get(rb_obj_class(state->self), id_fields);
|
833
|
+
VALUE members = rb_hash_new();
|
834
|
+
for (long i = 0; i < RARRAY_LEN(state->fields); i++) {
|
835
|
+
state->field = rb_ary_entry(state->fields, i);
|
836
|
+
struct cField_data *field_data;
|
837
|
+
TypedData_Get_Struct(state->field, struct cField_data, &cField_type, field_data);
|
838
|
+
rb_hash_aset(members, ID2SYM(field_data->getter),
|
839
|
+
rb_funcall(state->self, id___shape_field, 3, rb_funcall(state->self, field_data->getter, 0), state->kind, state->field));
|
840
|
+
}
|
841
|
+
return members;
|
842
|
+
}
|
843
|
+
|
844
|
+
static ID id___shape_fields;
|
845
|
+
|
846
|
+
static VALUE cStructure_shape_fields(VALUE self, VALUE kind) {
|
847
|
+
struct shape_fields_state state = {self, Qnil, Qnil, kind};
|
848
|
+
return rb_rescue(&cStructure_shape_fields_wrapper, (VALUE)&state,
|
849
|
+
&cStructure_fields_rescue, (VALUE)&state);
|
850
|
+
}
|
851
|
+
|
852
|
+
static ID id___load;
|
853
|
+
|
854
|
+
static inline VALUE cStructure_load(int argc, VALUE *argv, VALUE self) {
|
855
|
+
VALUE input;
|
856
|
+
VALUE input_big;
|
857
|
+
VALUE parent;
|
858
|
+
VALUE index;
|
859
|
+
rb_scan_args(argc, argv, "22", &input, &input_big, &parent, &index);
|
860
|
+
rb_funcall(self, id___set_load_state, 4, input, input_big, parent, index);
|
861
|
+
rb_funcall(self, id___load_fields, 0);
|
862
|
+
rb_funcall(self, id___unset_load_state, 0);
|
863
|
+
return self;
|
864
|
+
}
|
865
|
+
|
866
|
+
static ID id___dump;
|
867
|
+
|
868
|
+
static inline VALUE cStructure_dump(int argc, VALUE *argv, VALUE self) {
|
869
|
+
VALUE output;
|
870
|
+
VALUE output_big;
|
871
|
+
VALUE parent;
|
872
|
+
VALUE index;
|
873
|
+
rb_scan_args(argc, argv, "22", &output, &output_big, &parent, &index);
|
874
|
+
rb_funcall(self, id___set_dump_state, 4, output, output_big, parent, index);
|
875
|
+
rb_funcall(self, id___dump_fields, 0);
|
876
|
+
rb_funcall(self, id___unset_dump_state, 0);
|
877
|
+
return self;
|
878
|
+
}
|
879
|
+
|
880
|
+
static ID id___convert;
|
881
|
+
|
882
|
+
static VALUE cStructure_convert(int argc, VALUE *argv, VALUE self) {
|
883
|
+
VALUE input;
|
884
|
+
VALUE output;
|
885
|
+
VALUE input_big;
|
886
|
+
VALUE output_big;
|
887
|
+
VALUE parent;
|
888
|
+
VALUE index;
|
889
|
+
rb_scan_args(argc, argv, "42", &input, &output, &input_big, &output_big, &parent, &index);
|
890
|
+
rb_funcall(self, id___set_convert_state, 6, input, output, input_big, output_big, parent, index);
|
891
|
+
rb_funcall(self, id___convert_fields, 0);
|
892
|
+
rb_funcall(self, id___unset_convert_state, 0);
|
893
|
+
return self;
|
894
|
+
}
|
895
|
+
|
896
|
+
static ID id___shape;
|
897
|
+
|
898
|
+
static VALUE cStructure_shape(int argc, VALUE *argv, VALUE self) {
|
899
|
+
VALUE previous_offset;
|
900
|
+
VALUE parent;
|
901
|
+
VALUE index;
|
902
|
+
VALUE kind;
|
903
|
+
rb_scan_args(argc, argv, "04", &previous_offset, &parent, &index, &kind);
|
904
|
+
if (NIL_P(previous_offset))
|
905
|
+
previous_offset = INT2FIX(0);
|
906
|
+
if (NIL_P(kind))
|
907
|
+
kind = cDataShape;
|
908
|
+
rb_funcall(self, id___set_size_state, 3, previous_offset, parent, index);
|
909
|
+
VALUE members = rb_funcall(self, id___shape_fields, 1, kind);
|
910
|
+
rb_funcall(self, id___unset_size_state, 0);
|
911
|
+
if (RARRAY_LEN(rb_funcall(rb_funcall(members, rb_intern("values"), 0), rb_intern("compact"), 0)) <= 0)
|
912
|
+
return Qnil;
|
913
|
+
return rb_class_new_instance(1, &members, kind);
|
914
|
+
}
|
915
|
+
|
916
|
+
static VALUE cStructure_singl_load(int argc, VALUE *argv, VALUE self) {
|
917
|
+
VALUE input;
|
918
|
+
VALUE input_big;
|
919
|
+
VALUE parent;
|
920
|
+
VALUE index;
|
921
|
+
VALUE length;
|
922
|
+
rb_scan_args(argc, argv, "14", &input, &input_big, &parent, &index, &length);
|
923
|
+
if (NIL_P(input_big))
|
924
|
+
input_big = rb_funcall(mLibBin, rb_intern("default_big?"), 0);
|
925
|
+
VALUE res;
|
926
|
+
if (!NIL_P(length)) {
|
927
|
+
long l = NUM2LONG(length);
|
928
|
+
res = rb_ary_new_capa(l);
|
929
|
+
for (long i = 0; i < l; i++) {
|
930
|
+
VALUE obj = rb_class_new_instance(0, NULL, self);
|
931
|
+
rb_funcall(obj, id___load, 4, input, input_big, parent, index);
|
932
|
+
rb_ary_store(res, i, obj);
|
933
|
+
}
|
934
|
+
return res;
|
935
|
+
} else {
|
936
|
+
res = rb_class_new_instance(0, NULL, self);
|
937
|
+
rb_funcall(res, id___load, 4, input, input_big, parent, index);
|
938
|
+
}
|
939
|
+
return res;
|
940
|
+
}
|
941
|
+
|
942
|
+
static VALUE cStructure_singl_dump(int argc, VALUE *argv, VALUE self) {
|
943
|
+
VALUE value;
|
944
|
+
VALUE output;
|
945
|
+
VALUE output_big;
|
946
|
+
VALUE parent;
|
947
|
+
VALUE index;
|
948
|
+
VALUE length;
|
949
|
+
rb_scan_args(argc, argv, "24", &value, &output, &output_big, &parent, &index, &length);
|
950
|
+
if (NIL_P(output_big))
|
951
|
+
output_big = rb_funcall(mLibBin, rb_intern("default_big?"), 0);
|
952
|
+
if (!NIL_P(length)) {
|
953
|
+
long l = NUM2LONG(length);
|
954
|
+
for (long i = 0; i < l; i++)
|
955
|
+
rb_funcall(rb_ary_entry(value, i), id___dump, 4, output, output_big, parent, index);
|
956
|
+
} else
|
957
|
+
rb_funcall(value, id___dump, 4, output, output_big, parent, index);
|
958
|
+
return value;
|
959
|
+
}
|
960
|
+
|
961
|
+
static VALUE cStructure_singl_convert(int argc, VALUE *argv, VALUE self) {
|
962
|
+
VALUE input;
|
963
|
+
VALUE output;
|
964
|
+
VALUE input_big;
|
965
|
+
VALUE output_big;
|
966
|
+
VALUE parent;
|
967
|
+
VALUE index;
|
968
|
+
VALUE length;
|
969
|
+
rb_scan_args(argc, argv, "25", &input, &output, &input_big, &output_big, &parent, &index, &length);
|
970
|
+
if (NIL_P(input_big))
|
971
|
+
input_big = rb_funcall(mLibBin, rb_intern("default_big?"), 0);
|
972
|
+
if (NIL_P(output_big))
|
973
|
+
output_big = RTEST(input_big) ? Qfalse : Qtrue;
|
974
|
+
VALUE res;
|
975
|
+
if (!NIL_P(length)) {
|
976
|
+
long l = NUM2LONG(length);
|
977
|
+
res = rb_ary_new_capa(l);
|
978
|
+
for (long i = 0; i < l; i++) {
|
979
|
+
VALUE obj = rb_class_new_instance(0, NULL, self);
|
980
|
+
rb_funcall(obj, id___convert, 6, input, output, input_big, output_big, parent, index);
|
981
|
+
rb_ary_store(res, i, obj);
|
982
|
+
}
|
983
|
+
} else {
|
984
|
+
res = rb_class_new_instance(0, NULL, self);
|
985
|
+
rb_funcall(res, id___convert, 6, input, output, input_big, output_big, parent, index);
|
986
|
+
}
|
987
|
+
return res;
|
988
|
+
}
|
989
|
+
|
990
|
+
static VALUE cStructure_singl_shape(int argc, VALUE *argv, VALUE self) {
|
991
|
+
VALUE value;
|
992
|
+
VALUE previous_offset;
|
993
|
+
VALUE parent;
|
994
|
+
VALUE index;
|
995
|
+
VALUE kind;
|
996
|
+
VALUE length;
|
997
|
+
rb_scan_args(argc, argv, "15", &value, &previous_offset, &parent, &index, &kind, &length);
|
998
|
+
if (NIL_P(previous_offset))
|
999
|
+
previous_offset = INT2FIX(0);
|
1000
|
+
if (NIL_P(kind))
|
1001
|
+
kind = cDataShape;
|
1002
|
+
VALUE res;
|
1003
|
+
if (!NIL_P(length)) {
|
1004
|
+
long l = NUM2LONG(length);
|
1005
|
+
res = rb_ary_new_capa(l);
|
1006
|
+
for (long i = 0; i < l; i++)
|
1007
|
+
rb_ary_store(res, i, rb_funcall(rb_ary_entry(value, i), id___shape, 4, previous_offset, parent, index, kind));
|
1008
|
+
res = rb_class_new_instance(1, &res, kind);
|
1009
|
+
} else
|
1010
|
+
res = rb_funcall(value, id___shape, 4, previous_offset, parent, index, kind);
|
1011
|
+
return res;
|
1012
|
+
}
|
1013
|
+
|
1014
|
+
static void define_cStructure() {
|
1015
|
+
id_tell = rb_intern("tell");
|
1016
|
+
id_seek = rb_intern("seek");
|
1017
|
+
id_fields = rb_intern("@fields");
|
1018
|
+
id_instance_exec = rb_intern("instance_exec");
|
1019
|
+
|
1020
|
+
id___set_load_state = rb_intern("__set_load_state");
|
1021
|
+
id___unset_load_state = rb_intern("__unset_load_state");
|
1022
|
+
id___load_field = rb_intern("__load_field");
|
1023
|
+
id___load_fields = rb_intern("__load_fields");
|
1024
|
+
id_load = rb_intern("load");
|
1025
|
+
id___load = rb_intern("__load");
|
1026
|
+
|
1027
|
+
id___set_dump_state = rb_intern("__set_dump_state");
|
1028
|
+
id___unset_dump_state = rb_intern("__unset_dump_state");
|
1029
|
+
id___dump_field = rb_intern("__dump_field");
|
1030
|
+
id___dump_fields = rb_intern("__dump_fields");
|
1031
|
+
id_dump = rb_intern("dump");
|
1032
|
+
id___dump = rb_intern("__dump");
|
1033
|
+
|
1034
|
+
id___set_convert_state = rb_intern("__set_convert_state");
|
1035
|
+
id___unset_convert_state = rb_intern("__unset_convert_state");
|
1036
|
+
id___convert_field = rb_intern("__convert_field");
|
1037
|
+
id___convert_fields = rb_intern("__convert_fields");
|
1038
|
+
id_convert = rb_intern("convert");
|
1039
|
+
id___convert = rb_intern("__convert");
|
1040
|
+
|
1041
|
+
id___set_size_state = rb_intern("__set_size_state");
|
1042
|
+
id___unset_size_state = rb_intern("__unset_size_state");
|
1043
|
+
id___shape_field = rb_intern("__shape_field");
|
1044
|
+
id___shape_fields = rb_intern("__shape_fields");
|
1045
|
+
id_shape = rb_intern("shape");
|
1046
|
+
id___shape = rb_intern("__shape");
|
1047
|
+
|
1048
|
+
cStructure = rb_define_class_under(mLibBin, "Structure", rb_cObject);
|
1049
|
+
rb_define_alloc_func(cStructure, cStructure_alloc);
|
1050
|
+
/**
|
1051
|
+
* Create new Structure object.
|
1052
|
+
* @return [Structure] a new Structure instance with state set to nil.
|
1053
|
+
*/
|
1054
|
+
rb_define_method(cStructure, "initialize", cStructure_initialize, 0);
|
1055
|
+
|
1056
|
+
DEFINE_STRUCT_STATE_ACCESSORS(parent);
|
1057
|
+
DEFINE_STRUCT_STATE_ACCESSORS(index);
|
1058
|
+
DEFINE_STRUCT_STATE_ACCESSORS(position);
|
1059
|
+
DEFINE_STRUCT_STATE_ACCESSORS(cur_position);
|
1060
|
+
DEFINE_STRUCT_STATE_ACCESSORS(input);
|
1061
|
+
DEFINE_STRUCT_STATE_ACCESSORS(output);
|
1062
|
+
DEFINE_STRUCT_STATE_ACCESSORS(input_big);
|
1063
|
+
DEFINE_STRUCT_STATE_ACCESSORS(output_big);
|
1064
|
+
|
1065
|
+
DEFINE_STRUCT_STATE_ACCESSORS(offset);
|
1066
|
+
DEFINE_STRUCT_STATE_ACCESSORS(condition);
|
1067
|
+
DEFINE_STRUCT_STATE_ACCESSORS(type);
|
1068
|
+
DEFINE_STRUCT_STATE_ACCESSORS(length);
|
1069
|
+
DEFINE_STRUCT_STATE_ACCESSORS(iterator);
|
1070
|
+
DEFINE_STRUCT_STATE_ACCESSORS(count);
|
1071
|
+
DEFINE_STRUCT_STATE_ACCESSORS(value);
|
1072
|
+
|
1073
|
+
/**
|
1074
|
+
* @overload __set_convert_state(input, output, input_big, output_big, parent, index)
|
1075
|
+
* Set attributes for conversion
|
1076
|
+
* @param input [IO] the stream to read data from
|
1077
|
+
* @param output [IO] the stream to write data to
|
1078
|
+
* @param input_big [Boolean] str endianness of +input+
|
1079
|
+
* @param output_big [Boolean] str endianness of +output+
|
1080
|
+
* @param parent [nil,Structure] the parent if it exists, nil otherwise
|
1081
|
+
* @param index [nil,Integer] the index if the structure is repeated, nil otherwise
|
1082
|
+
* @return [nil]
|
1083
|
+
* @example
|
1084
|
+
* # Orignal Ruby implementation
|
1085
|
+
* def __set_convert_state(input, output, input_big, output_big, parent, index)
|
1086
|
+
* __input_big = input_big
|
1087
|
+
* __output_big = output_big
|
1088
|
+
* __input = input
|
1089
|
+
* __output = output
|
1090
|
+
* __parent = parent
|
1091
|
+
* __index = index
|
1092
|
+
* __position = input.tell
|
1093
|
+
* __cur_position = __position
|
1094
|
+
* end
|
1095
|
+
*/
|
1096
|
+
rb_define_method(cStructure, "__set_convert_state", cStructure_set_convert_state, 6);
|
1097
|
+
/**
|
1098
|
+
* Unset attributes after conversion.
|
1099
|
+
* @return [nil]
|
1100
|
+
* @example
|
1101
|
+
* # Orignal Ruby implementation
|
1102
|
+
* def __unset_convert_state
|
1103
|
+
* __input_big = nil
|
1104
|
+
* __output_big = nil
|
1105
|
+
* __input = nil
|
1106
|
+
* __output = nil
|
1107
|
+
* __parent = nil
|
1108
|
+
* __index = nil
|
1109
|
+
* __position = nil
|
1110
|
+
* __cur_position = nil
|
1111
|
+
* end
|
1112
|
+
*/
|
1113
|
+
rb_define_method(cStructure, "__unset_convert_state", cStructure_unset_convert_state, 0);
|
1114
|
+
/**
|
1115
|
+
* @overload __set_size_state(position, parent, index)
|
1116
|
+
* Set attributes for computing size or shape
|
1117
|
+
* @param position [Integer] The position of the field
|
1118
|
+
* @param parent [nil,Structure] the parent if it exists, nil otherwise
|
1119
|
+
* @param index [nil,Integer] the index if the structure is repeated, nil otherwise
|
1120
|
+
* @return [nil]
|
1121
|
+
* @example
|
1122
|
+
* # Orignal Ruby implementation
|
1123
|
+
* def __set_size_state(position, parent, index)
|
1124
|
+
* __parent = parent
|
1125
|
+
* __index = index
|
1126
|
+
* __position = position
|
1127
|
+
* __cur_position = __position
|
1128
|
+
* end
|
1129
|
+
*/
|
1130
|
+
rb_define_method(cStructure, "__set_size_state", cStructure_set_size_state, 3);
|
1131
|
+
/**
|
1132
|
+
* Unset attributes after size or shape computation
|
1133
|
+
* @return [nil]
|
1134
|
+
* @example
|
1135
|
+
* # Orignal Ruby implementation
|
1136
|
+
* def __unset_size_state
|
1137
|
+
* __parent = nil
|
1138
|
+
* __index = nil
|
1139
|
+
* __position = nil
|
1140
|
+
* __cur_position = nil
|
1141
|
+
* end
|
1142
|
+
*/
|
1143
|
+
rb_define_method(cStructure, "__unset_size_state", cStructure_unset_size_state, 0);
|
1144
|
+
/**
|
1145
|
+
* @overload __set_load_state(input, input_big, parent, index)
|
1146
|
+
* Set attributes for loading
|
1147
|
+
* @param input [IO] the stream to read data from
|
1148
|
+
* @param input_big [Boolean] str endianness of +input+
|
1149
|
+
* @param parent [nil,Structure] the parent if it exists, nil otherwise
|
1150
|
+
* @param index [nil,Integer] the index if the structure is repeated, nil otherwise
|
1151
|
+
* @return [nil]
|
1152
|
+
* @example
|
1153
|
+
* # Orignal Ruby implementation
|
1154
|
+
* def __set_load_state(input, input_big, parent, index)
|
1155
|
+
* __input_big = input_big
|
1156
|
+
* __input = input
|
1157
|
+
* __parent = parent
|
1158
|
+
* __index = index
|
1159
|
+
* __position = input.tell
|
1160
|
+
* __cur_position = __position
|
1161
|
+
* end
|
1162
|
+
*/
|
1163
|
+
rb_define_method(cStructure, "__set_load_state", cStructure_set_load_state, 4);
|
1164
|
+
/**
|
1165
|
+
* Unset attributes after loading
|
1166
|
+
* @return [nil]
|
1167
|
+
* @example
|
1168
|
+
* # Orignal Ruby implementation
|
1169
|
+
* def __unset_load_state
|
1170
|
+
* __input_big = nil
|
1171
|
+
* __input = nil
|
1172
|
+
* __parent = nil
|
1173
|
+
* __index = nil
|
1174
|
+
* __position = nil
|
1175
|
+
* __cur_position = nil
|
1176
|
+
* end
|
1177
|
+
*/
|
1178
|
+
rb_define_method(cStructure, "__unset_load_state", cStructure_unset_load_state, 0);
|
1179
|
+
/**
|
1180
|
+
* @overload __set_dump_state(output, output_big, parent, index)
|
1181
|
+
* Set attributes for dumping
|
1182
|
+
* @param output [IO] the stream to write data to
|
1183
|
+
* @param output_big [Boolean] str endianness of +output+
|
1184
|
+
* @param parent [nil,Structure] the parent if it exists, nil otherwise
|
1185
|
+
* @param index [nil,Integer] the index if the structure is repeated, nil otherwise
|
1186
|
+
* @return [nil]
|
1187
|
+
* @example
|
1188
|
+
* # Orignal Ruby implementation
|
1189
|
+
* def __set_dump_state(output, output_big, parent, index)
|
1190
|
+
* __output_big = output_big
|
1191
|
+
* __output = output
|
1192
|
+
* __parent = parent
|
1193
|
+
* __index = index
|
1194
|
+
* __position = output.tell
|
1195
|
+
* __cur_position = __position
|
1196
|
+
* end
|
1197
|
+
*/
|
1198
|
+
rb_define_method(cStructure, "__set_dump_state", cStructure_set_dump_state, 4);
|
1199
|
+
/**
|
1200
|
+
* Unset attributes after dumping
|
1201
|
+
* @return [nil]
|
1202
|
+
* @example
|
1203
|
+
* # Orignal Ruby implementation
|
1204
|
+
* def __unset_dump_state
|
1205
|
+
* __output_big = nil
|
1206
|
+
* __output = nil
|
1207
|
+
* __parent = nil
|
1208
|
+
* __index = nil
|
1209
|
+
* __position = nil
|
1210
|
+
* __cur_position = nil
|
1211
|
+
* end
|
1212
|
+
*/
|
1213
|
+
rb_define_method(cStructure, "__unset_dump_state", cStructure_unset_dump_state, 0);
|
1214
|
+
|
1215
|
+
/**
|
1216
|
+
* @overload __decode_expression(expression)
|
1217
|
+
* Decode the given expression in the context of the receiver.
|
1218
|
+
* @param expression [Proc,Object] the expression to decode
|
1219
|
+
* @return [Object] the decoded value
|
1220
|
+
* @note Do not overload, this is not called through the usual ruby dispatch for performance reasons
|
1221
|
+
* @example
|
1222
|
+
* # Original Ruby implementation
|
1223
|
+
* def __decode_expression(expression)
|
1224
|
+
* if expression.is_a?(Proc)
|
1225
|
+
* instance_exec &expression
|
1226
|
+
* else
|
1227
|
+
* expression
|
1228
|
+
* end
|
1229
|
+
* end
|
1230
|
+
*/
|
1231
|
+
rb_define_method(cStructure, "__decode_expression", cStructure_decode_expression, 1);
|
1232
|
+
/**
|
1233
|
+
* @overload __decode_expect(expect, value)
|
1234
|
+
* Decode the given expect expression, given the field value.
|
1235
|
+
* @param expect [Proc,Object,nil] the expression to decode
|
1236
|
+
* @param value [Object] the field value to validate
|
1237
|
+
* @return [Object] returns +value+ if validated. If expect is a Proc, the proc will be passed +value+
|
1238
|
+
* as an argument and be evaluated. If expect is a scalar, +expect+ and +value+ will be tested for equality.
|
1239
|
+
* If the result of the evaluation or the test is truthy, value is validate. Else an exception is raised.
|
1240
|
+
* @example
|
1241
|
+
* # Original Ruby implementation
|
1242
|
+
* def __decode_expect(expect, value)
|
1243
|
+
* return value if expect.nil?
|
1244
|
+
* if expect.is_a?(Proc)
|
1245
|
+
* raise "could not validate field value: #{value}" unless instance_exec(value, &expect)
|
1246
|
+
* else
|
1247
|
+
* raise "could not validate field value: #{value} expected: #{expect}" unless expect == value
|
1248
|
+
* end
|
1249
|
+
* return value
|
1250
|
+
* end
|
1251
|
+
*/
|
1252
|
+
rb_define_method(cStructure, "__decode_expect", cStructure_decode_expect, 2);
|
1253
|
+
/**
|
1254
|
+
* @overload __decode_seek_offset(offset, relative_offset, align)
|
1255
|
+
* Decode the offset and seek to this position in the active streams.
|
1256
|
+
* @param offset [Proc,Integer,nil] the expression to decode
|
1257
|
+
* @param relative_offset [Boolean] the offset should be relative to the structure base (+__position+)
|
1258
|
+
* @param align [false,Integer] the required alignement of the field
|
1259
|
+
* @return [nil,false,Integer] return nil if no offset was specified, an Integer if the active streams
|
1260
|
+
* had to seek, or false if a zero offset was computed.
|
1261
|
+
* @note Do not overload, this is not called through the usual ruby dispatch for performance reasons
|
1262
|
+
* @example
|
1263
|
+
* # Original Ruby implementation
|
1264
|
+
* def __decode_seek_offset(offset, relative_offset, align)
|
1265
|
+
* cur_pos = nil
|
1266
|
+
* if !offset
|
1267
|
+
* return nil unless align
|
1268
|
+
* cur_pos =
|
1269
|
+
* if __input
|
1270
|
+
* __input.tell
|
1271
|
+
* elsif __output
|
1272
|
+
* __output.tell
|
1273
|
+
* else
|
1274
|
+
* __cur_position
|
1275
|
+
* end
|
1276
|
+
* pad = cur_pos % align
|
1277
|
+
* return nil if pad == 0
|
1278
|
+
* cur_pos += align - pad
|
1279
|
+
* else
|
1280
|
+
* cur_pos = __decode_expression(offset)
|
1281
|
+
* return false if cur_pos == 0x0
|
1282
|
+
* cur_pos += __position if relative_offset
|
1283
|
+
* cur_pos += align - (cur_pos % align) if align && cur_pos % align > 0
|
1284
|
+
* end
|
1285
|
+
* __cur_position = cur_pos
|
1286
|
+
* __input.seek(cur_pos) if __input
|
1287
|
+
* __output.seek(cur_pos) if __output
|
1288
|
+
* cur_pos
|
1289
|
+
* end
|
1290
|
+
*/
|
1291
|
+
rb_define_method(cStructure, "__decode_seek_offset", cStructure_decode_seek_offset, 3);
|
1292
|
+
/**
|
1293
|
+
* @overload __decode_condition(condition)
|
1294
|
+
* Decode the condition expression
|
1295
|
+
* @param condition [Proc,Boolean,nil] the expression to decode
|
1296
|
+
* @return [Boolean] the field is active
|
1297
|
+
* @note Do not overload, this is not called through the usual ruby dispatch for performance reasons
|
1298
|
+
* @example
|
1299
|
+
* # Original Ruby implementation
|
1300
|
+
* def __decode_condition(condition)
|
1301
|
+
* return true unless condition
|
1302
|
+
* __decode_expression(condition)
|
1303
|
+
* end
|
1304
|
+
*/
|
1305
|
+
rb_define_method(cStructure, "__decode_condition", cStructure_decode_condition, 1);
|
1306
|
+
/**
|
1307
|
+
* @overload __decode_count(count)
|
1308
|
+
* Decode the count expression.
|
1309
|
+
* @param count [Proc,Integer,nil] the expression to decode
|
1310
|
+
* @return [Integer] 1 if +count+ is nil, the decoded count otherwise
|
1311
|
+
* @note Do not overload, this is not called through the usual ruby dispatch for performance reasons
|
1312
|
+
* @example
|
1313
|
+
* # Original Ruby implementation
|
1314
|
+
* def __decode_count(count)
|
1315
|
+
* return 1 unless count
|
1316
|
+
* __decode_expression(count)
|
1317
|
+
* end
|
1318
|
+
*/
|
1319
|
+
rb_define_method(cStructure, "__decode_count", cStructure_decode_count, 1);
|
1320
|
+
/**
|
1321
|
+
* @overload __decode_type(type)
|
1322
|
+
* Decode the type expression.
|
1323
|
+
* @param type [Proc,Class] the expression to decode
|
1324
|
+
* @return [Class] the decoded type
|
1325
|
+
* @note Do not overload, this is not called through the usual ruby dispatch for performance reasons
|
1326
|
+
* @example
|
1327
|
+
* # Original Ruby implementation
|
1328
|
+
* def __decode_type(type)
|
1329
|
+
* __decode_expression(type)
|
1330
|
+
* end
|
1331
|
+
*/
|
1332
|
+
rb_define_method(cStructure, "__decode_type", cStructure_decode_type, 1);
|
1333
|
+
/**
|
1334
|
+
* @overload __decode_length(length)
|
1335
|
+
* Decode the length expression.
|
1336
|
+
* @param length [Proc,Integer,nil] the expression to decode
|
1337
|
+
* @return [Integer,nil] nil if the field is not a vector, or the
|
1338
|
+
* length of the vector
|
1339
|
+
* @note Do not overload, this is not called through the usual ruby dispatch for performance reasons
|
1340
|
+
* @example
|
1341
|
+
* # Original Ruby implementation
|
1342
|
+
* def __decode_length(length)
|
1343
|
+
* __decode_expression(length)
|
1344
|
+
* end
|
1345
|
+
*/
|
1346
|
+
rb_define_method(cStructure, "__decode_length", cStructure_decode_length, 1);
|
1347
|
+
/**
|
1348
|
+
* @overload __decode_static_conditions(field)
|
1349
|
+
* Sets field specific context. Return nil if the field is inactive.
|
1350
|
+
* If the field is a sequence, only +__count+ is set, if not,
|
1351
|
+
* +__offset+, +__condition+, +__type+, and +__count+ are
|
1352
|
+
* also set.
|
1353
|
+
* @param field [Field] the field descriptor
|
1354
|
+
* @return [Integer,nil] nil if the field is inactive, the repetition count otherwise
|
1355
|
+
* @note Do not overload, this is not called through the usual ruby dispatch for performance reasons
|
1356
|
+
* @example
|
1357
|
+
* # Original Ruby implementation
|
1358
|
+
* def __decode_static_conditions(field)
|
1359
|
+
* __offset = nil
|
1360
|
+
* __condition = nil
|
1361
|
+
* __type = nil
|
1362
|
+
* __length = nil
|
1363
|
+
* __count = nil
|
1364
|
+
* unless field.sequence?
|
1365
|
+
* __offset = __decode_seek_offset(field.offset, field.relative_offset?, field.align)
|
1366
|
+
* return nil if __offset == false
|
1367
|
+
* __condition = __decode_condition(field.condition)
|
1368
|
+
* return nil unless __condition
|
1369
|
+
* __type = __decode_type(field.type)
|
1370
|
+
* __length = __decode_length(field.length)
|
1371
|
+
* end
|
1372
|
+
* __count = __decode_count(field.count)
|
1373
|
+
* end
|
1374
|
+
*/
|
1375
|
+
rb_define_method(cStructure, "__decode_static_conditions", cStructure_decode_static_conditions, 1);
|
1376
|
+
/**
|
1377
|
+
* @overload __decode_dynamic_conditions(field)
|
1378
|
+
* Sets field repetition specific context.
|
1379
|
+
* Namely +__offset+, +__condition+, +__type+, and +__length+
|
1380
|
+
* should be set if the field repetition is active.
|
1381
|
+
* @param field [Field] the field descriptor
|
1382
|
+
* @return [Boolean] field repetition is active
|
1383
|
+
* @note Do not overload, this is not called through the usual ruby dispatch for performance reasons.
|
1384
|
+
* @example
|
1385
|
+
* # Original Ruby implementation
|
1386
|
+
* def __decode_dynamic_conditions(field)
|
1387
|
+
* return true unless field.sequence?
|
1388
|
+
* __offset = nil
|
1389
|
+
* __condition = nil
|
1390
|
+
* __type = nil
|
1391
|
+
* __length = nil
|
1392
|
+
* __offset = __decode_seek_offset(field.offset, field.relative_offset?, field.align)
|
1393
|
+
* return false if __offset == false
|
1394
|
+
* __condition = __decode_condition(field.condition)
|
1395
|
+
* return false unless __condition
|
1396
|
+
* __type = __decode_type(field.type)
|
1397
|
+
* __length = __decode_length(field.length)
|
1398
|
+
* return true
|
1399
|
+
* end
|
1400
|
+
*/
|
1401
|
+
rb_define_method(cStructure, "__decode_dynamic_conditions", cStructure_decode_dynamic_conditions, 1);
|
1402
|
+
|
1403
|
+
/**
|
1404
|
+
* Restore the field specific context.
|
1405
|
+
* @return nil
|
1406
|
+
* @example
|
1407
|
+
* # Original Ruby implementation
|
1408
|
+
* def __restore_context
|
1409
|
+
* __iterator = nil
|
1410
|
+
* __type = nil
|
1411
|
+
* __length = nil
|
1412
|
+
* __count = nil
|
1413
|
+
* __offset = nil
|
1414
|
+
* __condition = nil
|
1415
|
+
* __value = nil
|
1416
|
+
* end
|
1417
|
+
*/
|
1418
|
+
rb_define_method(cStructure, "__restore_context", cStructure_restore_context, 0);
|
1419
|
+
|
1420
|
+
/**
|
1421
|
+
* @overload __convert_field(field)
|
1422
|
+
* Load and dump the value of a structure field.
|
1423
|
+
* @param field [Field] the field descriptor
|
1424
|
+
* @return the field value or nil if the field was inactive
|
1425
|
+
* @example
|
1426
|
+
* # Original Ruby implementation
|
1427
|
+
* def __convert_field(field)
|
1428
|
+
* return nil if __decode_static_conditions(field).nil?
|
1429
|
+
* vs = __count.times.collect do |it|
|
1430
|
+
* __iterator = it
|
1431
|
+
* if __decode_dynamic_conditions(field)
|
1432
|
+
* __value = __type::convert(__input, __output, __input_big, __output_big, self, it, __length)
|
1433
|
+
* __decode_expect(field.expect, __value)
|
1434
|
+
* else
|
1435
|
+
* nil
|
1436
|
+
* end
|
1437
|
+
* end
|
1438
|
+
* __restore_context
|
1439
|
+
* vs = vs.first unless field.count
|
1440
|
+
* vs
|
1441
|
+
* end
|
1442
|
+
*/
|
1443
|
+
rb_define_method(cStructure, "__convert_field", cStructure_convert_field, 1);
|
1444
|
+
/**
|
1445
|
+
* @overload __load_field(field)
|
1446
|
+
* Load the value of a structure field.
|
1447
|
+
* @param field [Field] the field descriptor
|
1448
|
+
* @return the field value or nil if the field was inactive
|
1449
|
+
* @example
|
1450
|
+
* # Original Ruby implementation
|
1451
|
+
* def __load_field(field)
|
1452
|
+
* return nil if __decode_static_conditions(field).nil?
|
1453
|
+
* vs = __count.times.collect do |it|
|
1454
|
+
* __iterator = it
|
1455
|
+
* if __decode_dynamic_conditions(field)
|
1456
|
+
* __value = __type::load(__input, __input_big, self, it, __length)
|
1457
|
+
* __decode_expect(field.expect, __value)
|
1458
|
+
* else
|
1459
|
+
* nil
|
1460
|
+
* end
|
1461
|
+
* end
|
1462
|
+
* __restore_context
|
1463
|
+
* vs = vs.first unless field.count
|
1464
|
+
* vs
|
1465
|
+
* end
|
1466
|
+
*/
|
1467
|
+
rb_define_method(cStructure, "__load_field", cStructure_load_field, 1);
|
1468
|
+
/**
|
1469
|
+
* @overload __dump_field(value, field)
|
1470
|
+
* Dump the value of a structure field.
|
1471
|
+
* @param value the field value
|
1472
|
+
* @param field [Field] the field descriptor
|
1473
|
+
* @return nil
|
1474
|
+
* @example
|
1475
|
+
* # Original Ruby implementation
|
1476
|
+
* def __dump_field(vs, field)
|
1477
|
+
* return nil if __decode_static_conditions(field).nil?
|
1478
|
+
* vs = [vs] unless field.count
|
1479
|
+
* __count.times do |it|
|
1480
|
+
* __iterator = it
|
1481
|
+
* if __decode_dynamic_conditions(field)
|
1482
|
+
* __value = vs[it]
|
1483
|
+
* __decode_expect(field.expect, __value)
|
1484
|
+
* __type::dump(__value, __output, __output_big, self, it, __length)
|
1485
|
+
* end
|
1486
|
+
* end
|
1487
|
+
* __restore_context
|
1488
|
+
* end
|
1489
|
+
*/
|
1490
|
+
rb_define_method(cStructure, "__dump_field", cStructure_dump_field, 2);
|
1491
|
+
/**
|
1492
|
+
* @overload __shape_field(value, kind, field)
|
1493
|
+
* Return the shape of the structure field.
|
1494
|
+
* @param value the field value
|
1495
|
+
* @param kind [Class] the class of the shape required
|
1496
|
+
* @param field [Field] the field descriptor
|
1497
|
+
* @return [nil,kind,Array<kind>] the field shape, or nil if the field was inactive
|
1498
|
+
* @example
|
1499
|
+
* # Original Ruby implementation
|
1500
|
+
* def __shape_field(vs, kind, field)
|
1501
|
+
* return nil if __decode_static_conditions(field).nil?
|
1502
|
+
* vs = [vs] unless field.count
|
1503
|
+
* vs = vs.each_with_index.collect do |v, it|
|
1504
|
+
* __iterator = it
|
1505
|
+
* if __decode_dynamic_conditions(field)
|
1506
|
+
* sh = __type::shape(v, __cur_position, self, it, kind, __length)
|
1507
|
+
* __cur_position = sh.last + 1 if sh.last && sh.last >= 0
|
1508
|
+
* sh
|
1509
|
+
* end
|
1510
|
+
* end
|
1511
|
+
* __restore_context
|
1512
|
+
* vs = field.count ? kind.new(vs) : vs.first
|
1513
|
+
* vs
|
1514
|
+
* end
|
1515
|
+
*/
|
1516
|
+
rb_define_method(cStructure, "__shape_field", cStructure_shape_field, 3);
|
1517
|
+
|
1518
|
+
/**
|
1519
|
+
* Load the fields of the structure. The load state must
|
1520
|
+
* have been set beforehand.
|
1521
|
+
* @return [Structure] self
|
1522
|
+
* @example
|
1523
|
+
* # Original Ruby implementation
|
1524
|
+
* def __load_fields
|
1525
|
+
* field = nil
|
1526
|
+
* begin
|
1527
|
+
* __fields.each { |field|
|
1528
|
+
* send("#{field.name}=", __load_field(field))
|
1529
|
+
* }
|
1530
|
+
* rescue
|
1531
|
+
* STDERR.puts "#{self.class}: #{field.name}(#{field.type})"
|
1532
|
+
* raise
|
1533
|
+
* end
|
1534
|
+
* self
|
1535
|
+
* end
|
1536
|
+
*/
|
1537
|
+
rb_define_method(cStructure, "__load_fields", cStructure_load_fields, 0);
|
1538
|
+
/**
|
1539
|
+
* Dump the fields of the structure. The dump state must
|
1540
|
+
* have been set beforehand.
|
1541
|
+
* @return [Structure] self
|
1542
|
+
* @example
|
1543
|
+
* # Original Ruby implementation
|
1544
|
+
* def __dump_fields
|
1545
|
+
* field = nil
|
1546
|
+
* begin
|
1547
|
+
* __fields.each { |field|
|
1548
|
+
* __dump_field(send(field.name), field)
|
1549
|
+
* }
|
1550
|
+
* rescue
|
1551
|
+
* STDERR.puts "#{self.class}: #{field.name}(#{field.type})"
|
1552
|
+
* raise
|
1553
|
+
* end
|
1554
|
+
* self
|
1555
|
+
* end
|
1556
|
+
*/
|
1557
|
+
rb_define_method(cStructure, "__dump_fields", cStructure_dump_fields, 0);
|
1558
|
+
/**
|
1559
|
+
* Convert the fields of the structure. The conversion
|
1560
|
+
* state must have been set beforehand.
|
1561
|
+
* @return [Structure] self
|
1562
|
+
* @example
|
1563
|
+
* # Original Ruby implementation
|
1564
|
+
* def __convert_fields
|
1565
|
+
* field = nil
|
1566
|
+
* begin
|
1567
|
+
* __fields.each { |field|
|
1568
|
+
* send("#{field.name}=", __convert_field(field))
|
1569
|
+
* }
|
1570
|
+
* rescue
|
1571
|
+
* STDERR.puts "#{self.class}: #{field.name}(#{field.type})"
|
1572
|
+
* raise
|
1573
|
+
* end
|
1574
|
+
* self
|
1575
|
+
* end
|
1576
|
+
*/
|
1577
|
+
rb_define_method(cStructure, "__convert_fields", cStructure_convert_fields, 0);
|
1578
|
+
/**
|
1579
|
+
* @overload __shape_fields(kind)
|
1580
|
+
* Return the shape of the structure fields in a Hash, indexed by the fields' names.
|
1581
|
+
* The size state must have been set beforehand.
|
1582
|
+
* @param kind [Class] the kind of structure to create
|
1583
|
+
* @return [Hash{Symbol=>kind}] the fields shape
|
1584
|
+
* @example
|
1585
|
+
* # Original Ruby implementation
|
1586
|
+
* def __shape_fields(kind)
|
1587
|
+
* members = {}
|
1588
|
+
* field = nil
|
1589
|
+
* begin
|
1590
|
+
* __fields.each { |field|
|
1591
|
+
* members[field.name] = __shape_field(send(field.name), kind, field)
|
1592
|
+
* }
|
1593
|
+
* rescue
|
1594
|
+
* LibBin.output.puts "#{self.class}: #{field.name}(#{field.type})" if LibBin.output
|
1595
|
+
* raise
|
1596
|
+
* end
|
1597
|
+
* return members
|
1598
|
+
* end
|
1599
|
+
*/
|
1600
|
+
rb_define_method(cStructure, "__shape_fields", cStructure_shape_fields, 1);
|
1601
|
+
|
1602
|
+
/**
|
1603
|
+
* @overload __load(input, input_big, parent = nil, index = nil)
|
1604
|
+
* Fill in the structure by loading it from +input+.
|
1605
|
+
* @param input [IO] the stream to load the structure from
|
1606
|
+
* @param input_big [Boolean] the endianness of +input+
|
1607
|
+
* @param parent [Structure] if given, the parent of the structure
|
1608
|
+
* @param index [Integer] if given, the structure is repeated and +index+ is the rank this structure
|
1609
|
+
* @return [Structure] self
|
1610
|
+
* @example
|
1611
|
+
* # Original Ruby implementation
|
1612
|
+
* def __load(input, input_big, parent = nil, index = nil)
|
1613
|
+
* __set_load_state(input, input_big, parent, index)
|
1614
|
+
* __load_fields
|
1615
|
+
* __unset_load_state
|
1616
|
+
* self
|
1617
|
+
* end
|
1618
|
+
*/
|
1619
|
+
rb_define_method(cStructure, "__load", cStructure_load, -1);
|
1620
|
+
/**
|
1621
|
+
* @overload __dump(output, output_big, parent = nil, index = nil)
|
1622
|
+
* Dump the structure to +output+.
|
1623
|
+
* @param output [IO] the stream to dump the structure to
|
1624
|
+
* @param output_big [Boolean] the endianness of +output+
|
1625
|
+
* @param parent [Structure] if given, the parent of the structure
|
1626
|
+
* @param index [Integer] if given, the structure is repeated and +index+ is the rank this structure
|
1627
|
+
* @return [Structure] self
|
1628
|
+
* @example
|
1629
|
+
* # Original Ruby implementation
|
1630
|
+
* def __dump(output, output_big, parent = nil, index = nil)
|
1631
|
+
* __set_dump_state(output, output_big, parent, index)
|
1632
|
+
* __dump_fields
|
1633
|
+
* __unset_dump_state
|
1634
|
+
* self
|
1635
|
+
* end
|
1636
|
+
*/
|
1637
|
+
rb_define_method(cStructure, "__dump", cStructure_dump, -1);
|
1638
|
+
/**
|
1639
|
+
* @overload __convert(input, output, input_big, output_big, parent = nil, index = nil)
|
1640
|
+
* Fill in the structure by loading it from +input+ and
|
1641
|
+
* dumping it to +output+.
|
1642
|
+
* @param input [IO] the stream to load the structure from
|
1643
|
+
* @param output [IO] the stream to dump the structure to
|
1644
|
+
* @param input_big [Boolean] the endianness of +input+
|
1645
|
+
* @param output_big [Boolean] the endianness of +output+
|
1646
|
+
* @param parent [Structure] if given, the parent of the structure
|
1647
|
+
* @param index [Integer] if given, the structure is repeated and +index+ is the rank this structure
|
1648
|
+
* @return [Structure] self
|
1649
|
+
* @example
|
1650
|
+
* # Original Ruby implementation
|
1651
|
+
* def __convert(input, output, input_big, output_big, parent = nil, index = nil)
|
1652
|
+
* __set_convert_state(input, output, input_big, output_big, parent, index)
|
1653
|
+
* __convert_fields
|
1654
|
+
* __unset_convert_state
|
1655
|
+
* self
|
1656
|
+
* end
|
1657
|
+
*/
|
1658
|
+
rb_define_method(cStructure, "__convert", cStructure_convert, -1);
|
1659
|
+
/**
|
1660
|
+
* @overload __shape(offset = 0, parent = nil, index = nil, kind = DataShape)
|
1661
|
+
* Return the shape of the structure.
|
1662
|
+
* @param offset [Integer] the base position of the field
|
1663
|
+
* @param parent [Structure] if given, the parent of the structure
|
1664
|
+
* @param index [Integer] if given, the structure is repeated and +index+ is the rank this structure
|
1665
|
+
* @param kind [Class] the kind of structure to create
|
1666
|
+
* @return [kind] the the shape of the structure
|
1667
|
+
* @example
|
1668
|
+
* # Original Ruby implementation
|
1669
|
+
* def __shape(previous_offset = 0, parent = nil, index = nil, kind = DataShape)
|
1670
|
+
* __set_size_state(previous_offset, parent, index)
|
1671
|
+
* members = __shape_fields(kind)
|
1672
|
+
* __unset_size_state
|
1673
|
+
* return nil if members.values.compact.size <= 0
|
1674
|
+
* kind::new(members)
|
1675
|
+
* end
|
1676
|
+
*/
|
1677
|
+
rb_define_method(cStructure, "__shape", cStructure_shape, -1);
|
1678
|
+
|
1679
|
+
/**
|
1680
|
+
* @overload load(input, input_big = LibBin::default_big?, parent = nil, index = nil, length = nil)
|
1681
|
+
* Load a structure from +input+.
|
1682
|
+
* @param input [IO] the stream to load the structure from
|
1683
|
+
* @param input_big [Boolean] the endianness of +input+
|
1684
|
+
* @param parent [Structure] if given, the parent of the structure
|
1685
|
+
* @param index [Integer] if given, the structure is repeated and +index+ is the rank this structure
|
1686
|
+
* @param length [Integer] if given, the length of the vector of structure
|
1687
|
+
* @return [Structure,Array<Structure>] a new strcuture, or
|
1688
|
+
* an array of structures if length was specified
|
1689
|
+
* @example
|
1690
|
+
* # Original Ruby implementation
|
1691
|
+
* def self.load(input, input_big = LibBin::default_big?, parent = nil, index = nil, length = nil)
|
1692
|
+
* if length
|
1693
|
+
* length.times.collect {
|
1694
|
+
* self.new.__load(input, input_big, parent, index)
|
1695
|
+
* }
|
1696
|
+
* else
|
1697
|
+
* self.new.__load(input, input_big, parent, index)
|
1698
|
+
* end
|
1699
|
+
* end
|
1700
|
+
*/
|
1701
|
+
rb_define_singleton_method(cStructure, "load", cStructure_singl_load, -1);
|
1702
|
+
/**
|
1703
|
+
* @overload dump(value, output, output_big = LibBin::default_big?, parent = nil, index = nil, length = nil)
|
1704
|
+
* Dump a structure to +output+.
|
1705
|
+
* @param value [Structure,Array<Structure>] the value of structure to dump
|
1706
|
+
* @param output [IO] the stream to dump the structure to
|
1707
|
+
* @param output_big [Boolean] the endianness of +output+
|
1708
|
+
* @param parent [Structure] if given, the parent of the structure
|
1709
|
+
* @param index [Integer] if given, the structure is repeated and +index+ is the rank this structure
|
1710
|
+
* @param length [Integer] if given, the length of the vector of structure
|
1711
|
+
* @return [Structure,Array<Structure>] +value+
|
1712
|
+
* @example
|
1713
|
+
* # Original Ruby implementation
|
1714
|
+
* def self.dump(value, output, output_big = LibBin::default_big?, parent = nil, index = nil, length = nil)
|
1715
|
+
* if length
|
1716
|
+
* length.times.each { |i|
|
1717
|
+
* value[i].__dump(output, output_big, parent, index)
|
1718
|
+
* }
|
1719
|
+
* value
|
1720
|
+
* else
|
1721
|
+
* value.__dump(output, output_big, parent, index)
|
1722
|
+
* end
|
1723
|
+
* end */
|
1724
|
+
rb_define_singleton_method(cStructure, "dump", cStructure_singl_dump, -1);
|
1725
|
+
/**
|
1726
|
+
* @overload convert(input, output, input_big = LibBin::default_big?, output_big = !input_big, parent = nil, index = nil, length = nil)
|
1727
|
+
* Convert a structure by loading it from +input+ and
|
1728
|
+
* dumping it to +output+. Returns the loaded structure.
|
1729
|
+
* @param input [IO] the stream to load the structure from
|
1730
|
+
* @param output [IO] the stream to dump the structure to
|
1731
|
+
* @param input_big [Boolean] the endianness of +input+
|
1732
|
+
* @param output_big [Boolean] the endianness of +output+
|
1733
|
+
* @param parent [Structure] if given, the parent of the structure
|
1734
|
+
* @param index [Integer] if given, the structure is repeated and +index+ is the rank this structure
|
1735
|
+
* @param length [Integer] if given, the length of the vector of structure
|
1736
|
+
* @return [Structure,Array<Structure>] a new strcuture, or
|
1737
|
+
* an array of structures if length was specified
|
1738
|
+
* @example
|
1739
|
+
* # Original Ruby implementation
|
1740
|
+
* def self.convert(input, output, input_big = LibBin::default_big?, output_big = !input_big, parent = nil, index = nil, length = nil)
|
1741
|
+
* if length
|
1742
|
+
* length.times.collect {
|
1743
|
+
* self.new.__convert(input, output, input_big, output_big, parent, index)
|
1744
|
+
* }
|
1745
|
+
* else
|
1746
|
+
* self.new.__convert(input, output, input_big, output_big, parent, index)
|
1747
|
+
* end
|
1748
|
+
* end
|
1749
|
+
*/
|
1750
|
+
rb_define_singleton_method(cStructure, "convert", cStructure_singl_convert, -1);
|
1751
|
+
/**
|
1752
|
+
* @overload shape(value, offset = 0, parent = nil, index = nil, kind = DataShape, length = nil)
|
1753
|
+
* Return the shape of the value.
|
1754
|
+
* @param value [Structure,Array<Structure>] the value of structure to get the shape of
|
1755
|
+
* @param offset [Integer] the base position of the field
|
1756
|
+
* @param parent [Structure] if given, the parent of the structure
|
1757
|
+
* @param index [Integer] if given, the structure is repeated and +index+ is the rank this structure
|
1758
|
+
* @param kind [Class] the kind of structure to create
|
1759
|
+
* @param length [Integer] if given, the length of the vector of structure
|
1760
|
+
* @return [kind] the the shape of the structure
|
1761
|
+
* @example
|
1762
|
+
* # Original Ruby implementation
|
1763
|
+
* def self.shape(value, previous_offset = 0, parent = nil, index = nil, kind = DataShape, length = nil)
|
1764
|
+
* if length
|
1765
|
+
* kind.new(length.times.collect { |i|
|
1766
|
+
* value[i].__shape(previous_offset, parent, index, kind)
|
1767
|
+
* })
|
1768
|
+
* else
|
1769
|
+
* value.__shape(previous_offset, parent, index, kind)
|
1770
|
+
* end
|
1771
|
+
* end
|
1772
|
+
*/
|
1773
|
+
rb_define_singleton_method(cStructure, "shape", cStructure_singl_shape, -1);
|
1774
|
+
}
|
1775
|
+
|
10
1776
|
static VALUE pghalf_from_string_p(VALUE self, VALUE str, VALUE pack_str) {
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
1777
|
+
(void)self;
|
1778
|
+
Check_Type(str, T_STRING);
|
1779
|
+
Check_Type(pack_str, T_STRING);
|
1780
|
+
VALUE arr = rb_funcall(str, rb_intern("unpack"), 1, pack_str);
|
1781
|
+
uint16_t val = NUM2USHORT(rb_funcall(arr, rb_intern("first"), 0));
|
1782
|
+
union float_u res;
|
16
1783
|
|
17
|
-
|
18
|
-
|
1784
|
+
res.i = pghalf_to_float(val);
|
1785
|
+
return DBL2NUM(res.f);
|
19
1786
|
}
|
20
1787
|
|
21
1788
|
static VALUE half_from_string_p(VALUE self, VALUE str, VALUE pack_str) {
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
1789
|
+
(void)self;
|
1790
|
+
Check_Type(str, T_STRING);
|
1791
|
+
Check_Type(pack_str, T_STRING);
|
1792
|
+
VALUE arr = rb_funcall(str, rb_intern("unpack"), 1, pack_str);
|
1793
|
+
uint16_t val = NUM2USHORT(rb_funcall(arr, rb_intern("first"), 0));
|
1794
|
+
union float_u res;
|
27
1795
|
|
28
|
-
|
29
|
-
|
1796
|
+
res.i = half_to_float(val);
|
1797
|
+
return DBL2NUM(res.f);
|
30
1798
|
}
|
31
1799
|
|
32
1800
|
static VALUE pghalf_to_string_p(VALUE self, VALUE number, VALUE pack_str) {
|
33
|
-
|
34
|
-
|
35
|
-
|
1801
|
+
(void)self;
|
1802
|
+
Check_Type(number, T_FLOAT);
|
1803
|
+
union float_u val;
|
1804
|
+
uint16_t res;
|
36
1805
|
|
37
|
-
|
38
|
-
|
39
|
-
|
1806
|
+
val.f = NUM2DBL(number);
|
1807
|
+
res = pghalf_from_float(val.i);
|
1808
|
+
VALUE arr = rb_ary_new3(1, UINT2NUM(res) );
|
40
1809
|
|
41
|
-
|
1810
|
+
return rb_funcall(arr, rb_intern("pack"), 1, pack_str);
|
42
1811
|
}
|
43
1812
|
|
44
1813
|
static VALUE half_to_string_p(VALUE self, VALUE number, VALUE pack_str) {
|
45
|
-
|
46
|
-
|
47
|
-
|
1814
|
+
(void)self;
|
1815
|
+
Check_Type(number, T_FLOAT);
|
1816
|
+
union float_u val;
|
1817
|
+
uint16_t res;
|
1818
|
+
|
1819
|
+
val.f = NUM2DBL(number);
|
1820
|
+
res = half_from_float(val.i);
|
1821
|
+
VALUE arr = rb_ary_new3(1, UINT2NUM(res) );
|
1822
|
+
|
1823
|
+
return rb_funcall(arr, rb_intern("pack"), 1, pack_str);
|
1824
|
+
}
|
1825
|
+
|
1826
|
+
static void define_cField() {
|
1827
|
+
id_gsub = rb_intern("gsub");
|
48
1828
|
|
49
|
-
|
50
|
-
|
51
|
-
|
1829
|
+
rb_str_dot_dot = rb_obj_freeze(rb_str_new_cstr(".."));
|
1830
|
+
rb_gc_register_mark_object(rb_str_dot_dot);
|
1831
|
+
rb_str___parent = rb_obj_freeze(rb_str_new_cstr("__parent"));
|
1832
|
+
rb_gc_register_mark_object(rb_str___parent);
|
1833
|
+
rb_str_backslash = rb_obj_freeze(rb_str_new_cstr("\\"));
|
1834
|
+
rb_gc_register_mark_object(rb_str_backslash);
|
1835
|
+
rb_str_dot = rb_obj_freeze(rb_str_new_cstr("."));
|
1836
|
+
rb_gc_register_mark_object(rb_str_dot);
|
52
1837
|
|
53
|
-
|
1838
|
+
cField = rb_define_class_under(cStructure, "Field", rb_cObject);
|
1839
|
+
rb_define_alloc_func(cField, cField_alloc);
|
1840
|
+
/**
|
1841
|
+
* @overload initialize(name, type, length, count, offset, sequence, condition, relative_offset, align, expect)
|
1842
|
+
* @param name [Symbol, String] the name of the field.
|
1843
|
+
* @param type [Class, String, Proc] the type of the field, as a Class, or
|
1844
|
+
* as a String or Proc that will be evaluated in the context of the
|
1845
|
+
* {Structure} instance.
|
1846
|
+
* @param length [nil, Integer, String, Proc] if given, consider the field a
|
1847
|
+
* vector of the type. The length is either a constant Integer of a
|
1848
|
+
* String or Proc that will be evaluated in the context of the
|
1849
|
+
* {Structure} instance.
|
1850
|
+
* @param count [nil, Integer, String, Proc] if given, consider the field is
|
1851
|
+
* repeated count times. The count is either a constant Integer of a
|
1852
|
+
* String or Proc that will be evaluated in the context of the
|
1853
|
+
* {Structure} instance.
|
1854
|
+
* @param offset [nil, integer, String, Proc] if given, the absolute offset in
|
1855
|
+
* the file, or the offset from the parent position, where the field can
|
1856
|
+
* be found. See relative offset. The offset is either a constant
|
1857
|
+
* Integer of a String or Proc that will be evaluated in the context
|
1858
|
+
* of the {Structure} instance.
|
1859
|
+
* @param sequence [Boolean] if true, +type+, +length+, +offset+, and
|
1860
|
+
* +condition+ are evaluated for each repetition.
|
1861
|
+
* @param condition [nil, String, Proc] if given, the field, or repetition of the
|
1862
|
+
* field can be conditionally present. The condition will be evaluated in
|
1863
|
+
* the context of the {Structure} instance.
|
1864
|
+
* @param relative_offset [Boolean] consider the +offset+ relative to
|
1865
|
+
* the field +parent+.
|
1866
|
+
* @param align [nil, Integer] if given, align the field. If given as an
|
1867
|
+
* Integer it must be a power of 2. Else the field is aligned to the
|
1868
|
+
* field's type preferred alignment
|
1869
|
+
* @param expect [nil, Proc, Object] if given as a Proc the proc must
|
1870
|
+
* evaluate to a truthy value or an exception will be raised. Else, the
|
1871
|
+
* object will be tested for equality, and an exception will be raised if
|
1872
|
+
* objects were not equal. Proc is evaluated in the context of the {Structure}
|
1873
|
+
* instance and #__value will be set. Each repetition is validated.
|
1874
|
+
* @return [Field] new Field
|
1875
|
+
*/
|
1876
|
+
rb_define_method(cField, "initialize", cField_initialize, 10);
|
1877
|
+
DEFINE_FIELD_STATE_GETTER(name);
|
1878
|
+
DEFINE_FIELD_STATE_GETTER(type);
|
1879
|
+
DEFINE_FIELD_STATE_GETTER(length);
|
1880
|
+
DEFINE_FIELD_STATE_GETTER(count);
|
1881
|
+
DEFINE_FIELD_STATE_GETTER(offset);
|
1882
|
+
DEFINE_FIELD_STATE_GETTER_BOOL(sequence);
|
1883
|
+
DEFINE_FIELD_STATE_GETTER(condition);
|
1884
|
+
DEFINE_FIELD_STATE_GETTER_BOOL(relative_offset);
|
1885
|
+
DEFINE_FIELD_STATE_GETTER(align);
|
1886
|
+
DEFINE_FIELD_STATE_GETTER(expect);
|
54
1887
|
}
|
55
1888
|
|
56
1889
|
void Init_libbin_c() {
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
1890
|
+
mLibBin = rb_define_module("LibBin");
|
1891
|
+
/**
|
1892
|
+
* @overload half_from_string(str, unpack_str)
|
1893
|
+
* Load (unpacks) a half precision floating point.
|
1894
|
+
* @param str [String] the strin to read the number from
|
1895
|
+
* @param unpack_str [String] the unpack format of the underlying 16bit integer
|
1896
|
+
* @return [Float] the ruby representation of the value
|
1897
|
+
* @example
|
1898
|
+
* # Read a half precision floating point value stored in 'str' in little endian fashion
|
1899
|
+
* value = half_from_string(str, "S<")
|
1900
|
+
*/
|
1901
|
+
rb_define_module_function(mLibBin, "half_from_string", half_from_string_p, 2);
|
1902
|
+
/**
|
1903
|
+
* @overload half_to_string(value, pack_str)
|
1904
|
+
* Convert a Numeric value to a half precision floating point and pack it into a string.
|
1905
|
+
* @param value [Numeric] the number to convert
|
1906
|
+
* @param pack_str [String] the pack format to store the underlying 16 bit integer representation of the value
|
1907
|
+
* @return [String] the packed half precision value
|
1908
|
+
* @example
|
1909
|
+
* # Stores a number as a half precision floating point value in a big endian fashion
|
1910
|
+
* str = half_to_string(value, "S>")
|
1911
|
+
*/
|
1912
|
+
rb_define_module_function(mLibBin, "half_to_string", half_to_string_p, 2);
|
1913
|
+
/**
|
1914
|
+
* @overload pghalf_from_string(str, unpack_str)
|
1915
|
+
* Load (unpacks) a half precision floating point as used by PlatinumGames in some formats.
|
1916
|
+
* @param str [String] the strin to read the number from
|
1917
|
+
* @param unpack_str [String] the unpack format of the underlying 16bit integer
|
1918
|
+
* @return [Float] the ruby representation of the value
|
1919
|
+
* @example
|
1920
|
+
* # Read a half precision floating point value stored in 'str' in little endian fashion
|
1921
|
+
* half_from_string(str, "S<")
|
1922
|
+
*/
|
1923
|
+
rb_define_module_function(mLibBin, "pghalf_from_string", pghalf_from_string_p, 2);
|
1924
|
+
/**
|
1925
|
+
* @overload pghalf_to_string(value, pack_str)
|
1926
|
+
* Convert a Numeric value to a half precision floating point as used by PlatinumGames in some formats, and pack it into a string.
|
1927
|
+
* @param value [Numeric] the number to convert
|
1928
|
+
* @param pack_str [String] the pack format to store the underlying 16 bit integer representation of the value
|
1929
|
+
* @return [String] the packed half precision value
|
1930
|
+
* @example
|
1931
|
+
* # Stores a number as a half precision floating point value in a big endian fashion
|
1932
|
+
* str = half_to_string(value, "S>")
|
1933
|
+
*/
|
1934
|
+
rb_define_module_function(mLibBin, "pghalf_to_string", pghalf_to_string_p, 2);
|
1935
|
+
cDataRange = rb_define_class_under(mLibBin, "DataRange", rb_cObject);
|
1936
|
+
cDataShape = rb_define_class_under(mLibBin, "DataShape", cDataRange);
|
1937
|
+
define_cStructure();
|
1938
|
+
define_cField();
|
1939
|
+
define_cScalar();
|
65
1940
|
}
|