type_array 0.1
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.
- data/.gitignore +19 -0
- data/.travis.yml +18 -0
- data/CHANGELOG.rdoc +4 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +18 -0
- data/README.rdoc +140 -0
- data/Rakefile +47 -0
- data/ext/type_array/array_buffer.c +183 -0
- data/ext/type_array/array_buffer.h +19 -0
- data/ext/type_array/data_view.c +574 -0
- data/ext/type_array/data_view.h +35 -0
- data/ext/type_array/extconf.rb +14 -0
- data/ext/type_array/jruby.h +9 -0
- data/ext/type_array/prelude.h +25 -0
- data/ext/type_array/rubinius.h +19 -0
- data/ext/type_array/ruby18.h +15 -0
- data/ext/type_array/ruby19.h +12 -0
- data/ext/type_array/type_array.c +540 -0
- data/ext/type_array/type_array.h +38 -0
- data/ext/type_array/type_array_ext.c +25 -0
- data/ext/type_array/type_array_ext.h +71 -0
- data/lib/type_array/io.rb +28 -0
- data/lib/type_array/version.rb +3 -0
- data/lib/type_array.rb +14 -0
- data/test/helper.rb +23 -0
- data/test/test_array_buffer.rb +132 -0
- data/test/test_data_view.rb +218 -0
- data/test/test_float_32_array.rb +36 -0
- data/test/test_float_64_array.rb +38 -0
- data/test/test_int_16_array.rb +37 -0
- data/test/test_int_32_array.rb +43 -0
- data/test/test_int_8_array.rb +29 -0
- data/test/test_type_array.rb +155 -0
- data/test/test_uint_16_array.rb +35 -0
- data/test/test_uint_32_array.rb +35 -0
- data/test/test_uint_8_array.rb +33 -0
- data/type_array.gemspec +22 -0
- metadata +112 -0
@@ -0,0 +1,574 @@
|
|
1
|
+
#include "type_array_ext.h"
|
2
|
+
|
3
|
+
/*
|
4
|
+
* :nodoc:
|
5
|
+
* Provides a low level view of a given ArrayBuffer instance. This is useful for lower level manipulation of byte streams
|
6
|
+
* and well suited for reading and writing structs / records from and to streams. Expect this to support structs in the
|
7
|
+
* near future. DataView object's underlying buffer's fixed as well - there's no way to manipulate it from Ruby.
|
8
|
+
*
|
9
|
+
*/
|
10
|
+
|
11
|
+
VALUE rb_cDataView;
|
12
|
+
|
13
|
+
static inline unsigned long rb_data_view_assert_offset(rb_data_view_t *view, VALUE idx)
|
14
|
+
{
|
15
|
+
unsigned long index;
|
16
|
+
index = FIX2ULONG(idx); \
|
17
|
+
if (index > view->byte_length) rb_raise(rb_eRangeError, "Offset out of range.");
|
18
|
+
return index;
|
19
|
+
}
|
20
|
+
|
21
|
+
/*
|
22
|
+
* :nodoc:
|
23
|
+
* GC mark callback
|
24
|
+
*
|
25
|
+
*/
|
26
|
+
static void rb_mark_data_view(void *ptr)
|
27
|
+
{
|
28
|
+
rb_data_view_t *view = (rb_data_view_t *)ptr;
|
29
|
+
if (view) rb_gc_mark(view->buf);
|
30
|
+
}
|
31
|
+
|
32
|
+
/*
|
33
|
+
* :nodoc:
|
34
|
+
* GC free callback
|
35
|
+
*
|
36
|
+
*/
|
37
|
+
void rb_free_data_view(void *ptr)
|
38
|
+
{
|
39
|
+
rb_data_view_t *view = (rb_data_view_t *)ptr;
|
40
|
+
#ifdef TYPE_ARRAY_DEBUG
|
41
|
+
printf(">> rb_free_data_view %p\n", ptr);
|
42
|
+
#endif
|
43
|
+
if (view) {
|
44
|
+
xfree(view);
|
45
|
+
view = NULL;
|
46
|
+
}
|
47
|
+
#ifdef TYPE_ARRAY_DEBUG
|
48
|
+
printf("<< rb_free_data_view %p\n", ptr);
|
49
|
+
#endif
|
50
|
+
}
|
51
|
+
|
52
|
+
/*
|
53
|
+
* call-seq:
|
54
|
+
* DataView.new(buf) => DataView
|
55
|
+
* DataView.new("buffer") => DataView
|
56
|
+
*
|
57
|
+
* Creates a new DataView instance. Both ArrayBuffer and data (String) constructors are supported.
|
58
|
+
*
|
59
|
+
* === Examples
|
60
|
+
* buf = ArrayBuffer.new(8) => ArrayBuffer
|
61
|
+
* view = DataView.new(buf) => DataView
|
62
|
+
*
|
63
|
+
* view = DataView.new(buf, 2) => DataView
|
64
|
+
* view.byte_offset => 2
|
65
|
+
* view.byte_length => 6
|
66
|
+
*
|
67
|
+
* view = DataView.new(buf, 2, 4) => DataView
|
68
|
+
* view.byte_offset => 2
|
69
|
+
* view.byte_length => 2
|
70
|
+
*
|
71
|
+
* view = DataView.new("buffer") => DataView
|
72
|
+
*
|
73
|
+
*/
|
74
|
+
static VALUE rb_data_view_s_new(int argc, VALUE *argv, VALUE klass)
|
75
|
+
{
|
76
|
+
VALUE data_view;
|
77
|
+
unsigned long new_byte_length;
|
78
|
+
rb_data_view_t *view = NULL;
|
79
|
+
VALUE obj, byte_offset, byte_length, buffer;
|
80
|
+
new_byte_length = 0;
|
81
|
+
rb_scan_args(argc, argv, "12", &obj, &byte_offset, &byte_length);
|
82
|
+
data_view = Data_Make_Struct(klass, rb_data_view_t, rb_mark_data_view, rb_free_data_view, view);
|
83
|
+
view->byte_offset = 0;
|
84
|
+
view->byte_length = 0;
|
85
|
+
if (rb_class_of(obj) == rb_cArrayBuffer) {
|
86
|
+
GetArrayBuffer(obj);
|
87
|
+
view->byte_length = buf->length;
|
88
|
+
view->buf = obj;
|
89
|
+
} else if (rb_type(obj) == T_STRING){
|
90
|
+
ArrayBufferEncode(obj);
|
91
|
+
buffer = rb_alloc_array_buffer((unsigned long)RSTRING_LEN(obj), (void *)RSTRING_PTR(obj));
|
92
|
+
GetArrayBuffer(buffer);
|
93
|
+
view->byte_length = buf->length;
|
94
|
+
view->buf = buffer;
|
95
|
+
} else {
|
96
|
+
rb_raise(rb_eTypeError, "DataView constructor %s not supported.", RSTRING_PTR(rb_obj_as_string(obj)));
|
97
|
+
}
|
98
|
+
if (!NIL_P(byte_offset)) {
|
99
|
+
Check_Type(byte_offset, T_FIXNUM);
|
100
|
+
view->byte_offset = FIX2ULONG(byte_offset);
|
101
|
+
if (view->byte_offset >= view->byte_length)
|
102
|
+
rb_raise(rb_eRangeError, "Byte offset out of range.");
|
103
|
+
}
|
104
|
+
if (!NIL_P(byte_length)) {
|
105
|
+
Check_Type(byte_length, T_FIXNUM);
|
106
|
+
new_byte_length = FIX2ULONG(byte_length);
|
107
|
+
if (new_byte_length > view->byte_length)
|
108
|
+
rb_raise(rb_eRangeError, "Byte length out of range.");
|
109
|
+
if ((view->byte_offset + new_byte_length) > view->byte_length)
|
110
|
+
rb_raise(rb_eRangeError, "Byte offset / length is not aligned.");
|
111
|
+
view->byte_length = new_byte_length;
|
112
|
+
}
|
113
|
+
view->byte_length -= view->byte_offset;
|
114
|
+
rb_obj_call_init(data_view, 0, NULL);
|
115
|
+
return data_view;
|
116
|
+
}
|
117
|
+
|
118
|
+
/*
|
119
|
+
* call-seq:
|
120
|
+
* view.byte_length => Fixnum
|
121
|
+
*
|
122
|
+
* Returns the size of the underlying buffer managed by this DataView instance.
|
123
|
+
*
|
124
|
+
* === Examples
|
125
|
+
* view = DataView.new("buffer") => DataView
|
126
|
+
* view.byte_length => 6
|
127
|
+
*
|
128
|
+
*/
|
129
|
+
static VALUE rb_data_view_byte_length(VALUE obj)
|
130
|
+
{
|
131
|
+
GetDataView(obj);
|
132
|
+
return ULONG2NUM(view->byte_length);
|
133
|
+
}
|
134
|
+
|
135
|
+
/*
|
136
|
+
* call-seq:
|
137
|
+
* view.byte_offset => Fixnum
|
138
|
+
*
|
139
|
+
* Returns the offset into the underlying buffer managed by this DataView instance.
|
140
|
+
*
|
141
|
+
* === Examples
|
142
|
+
* view = DataView.new("buffer") => DataView
|
143
|
+
* view.byte_offset => 0
|
144
|
+
*
|
145
|
+
* view = DataView.new("buffer", 2) => DataView
|
146
|
+
* view.byte_offset => 2
|
147
|
+
*
|
148
|
+
*/
|
149
|
+
static VALUE rb_data_view_byte_offset(VALUE obj)
|
150
|
+
{
|
151
|
+
GetDataView(obj);
|
152
|
+
return ULONG2NUM(view->byte_offset);
|
153
|
+
}
|
154
|
+
|
155
|
+
/*
|
156
|
+
* call-seq:
|
157
|
+
* view.buffer => String
|
158
|
+
*
|
159
|
+
* Returns the underlying buffer managed by this DataView instance.
|
160
|
+
*
|
161
|
+
* === Examples
|
162
|
+
* view = DataView.new("buffer") => DataView
|
163
|
+
* view.buffer => ArrayBuffer
|
164
|
+
*
|
165
|
+
*/
|
166
|
+
static VALUE rb_data_view_buffer(VALUE obj)
|
167
|
+
{
|
168
|
+
GetDataView(obj);
|
169
|
+
return view->buf;
|
170
|
+
}
|
171
|
+
|
172
|
+
/*
|
173
|
+
* call-seq:
|
174
|
+
* view.set_int8(2, 2) => nil
|
175
|
+
*
|
176
|
+
* Sets an int8 value at a given offset
|
177
|
+
*
|
178
|
+
* === Examples
|
179
|
+
* buf = ArrayBuffer.new(100) => ArrayBuffer
|
180
|
+
* view = DataView.new(buf) => DataView
|
181
|
+
* view.set_int8(2, 5) => nil
|
182
|
+
* view.set_int8(3, -3) => nil
|
183
|
+
*
|
184
|
+
*/
|
185
|
+
static VALUE rb_data_view_set_int8(VALUE obj, VALUE offset_, VALUE item_)
|
186
|
+
{
|
187
|
+
int argc;
|
188
|
+
VALUE argv[3];
|
189
|
+
argc = 3;
|
190
|
+
argv[0] = offset_;
|
191
|
+
argv[1] = item_;
|
192
|
+
argv[2] = Qfalse;
|
193
|
+
DataViewAset(obj);
|
194
|
+
rb_type_array_set_int8(buf->buf, index, NUM2CHR(item), little_endian);
|
195
|
+
return Qnil;
|
196
|
+
}
|
197
|
+
|
198
|
+
/*
|
199
|
+
* call-seq:
|
200
|
+
* view.get_int8(2) => Fixnum
|
201
|
+
*
|
202
|
+
* Gets an int8 value from a given offset
|
203
|
+
*
|
204
|
+
* === Examples
|
205
|
+
* buf = ArrayBuffer.new(100) => ArrayBuffer
|
206
|
+
* view = DataView.new(buf) => DataView
|
207
|
+
* view.set_int8(2, 5) => nil
|
208
|
+
* view.get_int8(2) => 5
|
209
|
+
*
|
210
|
+
*/
|
211
|
+
static VALUE rb_data_view_get_int8(VALUE obj, VALUE offset_)
|
212
|
+
{
|
213
|
+
int argc;
|
214
|
+
VALUE argv[2];
|
215
|
+
argc = 1;
|
216
|
+
argv[0] = offset_;
|
217
|
+
argv[1] = Qfalse;
|
218
|
+
DataViewAget(obj);
|
219
|
+
return TACHR2FIX(rb_type_array_get_int8(buf->buf, index, little_endian));
|
220
|
+
}
|
221
|
+
|
222
|
+
/*
|
223
|
+
* call-seq:
|
224
|
+
* view.set_uint8(2, 2) => nil
|
225
|
+
*
|
226
|
+
* Sets an unsigned int8 value at a given offset.
|
227
|
+
*
|
228
|
+
* === Examples
|
229
|
+
* buf = ArrayBuffer.new(100) => ArrayBuffer
|
230
|
+
* view = DataView.new(buf) => DataView
|
231
|
+
* view.set_uint8(2, 5) => nil
|
232
|
+
*
|
233
|
+
*/
|
234
|
+
static VALUE rb_data_view_set_uint8(VALUE obj, VALUE offset_, VALUE item_)
|
235
|
+
{
|
236
|
+
int argc;
|
237
|
+
VALUE argv[3];
|
238
|
+
argc = 3;
|
239
|
+
argv[0] = offset_;
|
240
|
+
argv[1] = item_;
|
241
|
+
argv[2] = Qfalse;
|
242
|
+
DataViewAset(obj);
|
243
|
+
rb_type_array_set_uint8(buf->buf, index, (unsigned char)NUM2CHR(item), little_endian);
|
244
|
+
return Qnil;
|
245
|
+
}
|
246
|
+
|
247
|
+
/*
|
248
|
+
* call-seq:
|
249
|
+
* view.get_uint8(2) => Fixnum
|
250
|
+
*
|
251
|
+
* Gets an unsigned int8 value from a given offset.
|
252
|
+
*
|
253
|
+
* === Examples
|
254
|
+
* buf = ArrayBuffer.new(100) => ArrayBuffer
|
255
|
+
* view = DataView.new(buf) => DataView
|
256
|
+
* view.set_uint8(2, 5) => nil
|
257
|
+
* view.get_uint8(2) => 5
|
258
|
+
*
|
259
|
+
*/
|
260
|
+
static VALUE rb_data_view_get_uint8(VALUE obj, VALUE offset_)
|
261
|
+
{
|
262
|
+
int argc;
|
263
|
+
VALUE argv[2];
|
264
|
+
argc = 1;
|
265
|
+
argv[0] = offset_;
|
266
|
+
argv[1] = Qfalse;
|
267
|
+
DataViewAget(obj);
|
268
|
+
return TACHR2FIX(rb_type_array_get_uint8(buf->buf, index, little_endian));
|
269
|
+
}
|
270
|
+
|
271
|
+
/*
|
272
|
+
* call-seq:
|
273
|
+
* view.set_int16(2, 20) => nil
|
274
|
+
*
|
275
|
+
* Sets an int16 value at a given offset, using the provided endianness.
|
276
|
+
*
|
277
|
+
* === Examples
|
278
|
+
* buf = ArrayBuffer.new(100) => ArrayBuffer
|
279
|
+
* view = DataView.new(buf) => DataView
|
280
|
+
* view.set_int16(2, 20) => nil
|
281
|
+
* view.set_int16(3, -2) => nil
|
282
|
+
*
|
283
|
+
*/
|
284
|
+
static VALUE rb_data_view_set_int16(int argc, VALUE *argv, VALUE obj)
|
285
|
+
{
|
286
|
+
DataViewAset(obj);
|
287
|
+
rb_type_array_set_int16(buf->buf, index, (short)NUM2INT(item), little_endian);
|
288
|
+
return Qnil;
|
289
|
+
}
|
290
|
+
|
291
|
+
/*
|
292
|
+
* call-seq:
|
293
|
+
* view.get_int16(2) => Fixnum
|
294
|
+
*
|
295
|
+
* Gets an int16 value from a given offset, using the provided endianness.
|
296
|
+
*
|
297
|
+
* === Examples
|
298
|
+
* buf = ArrayBuffer.new(100) => ArrayBuffer
|
299
|
+
* view = DataView.new(buf) => DataView
|
300
|
+
* view.set_int16(2, 20) => nil
|
301
|
+
* view.get_int16(2) => 20
|
302
|
+
*
|
303
|
+
*/
|
304
|
+
static VALUE rb_data_view_get_int16(int argc, VALUE *argv, VALUE obj)
|
305
|
+
{
|
306
|
+
DataViewAget(obj);
|
307
|
+
return INT2FIX(rb_type_array_get_int16(buf->buf, index, little_endian));
|
308
|
+
}
|
309
|
+
|
310
|
+
/*
|
311
|
+
* call-seq:
|
312
|
+
* view.set_uint16(2, 20) => nil
|
313
|
+
*
|
314
|
+
* Sets an unsigned int16 value at a given offset, using the provided endianness.
|
315
|
+
*
|
316
|
+
* === Examples
|
317
|
+
* buf = ArrayBuffer.new(100) => ArrayBuffer
|
318
|
+
* view = DataView.new(buf) => DataView
|
319
|
+
* view.set_uint16(2, 20) => nil
|
320
|
+
*
|
321
|
+
*/
|
322
|
+
static VALUE rb_data_view_set_uint16(int argc, VALUE *argv, VALUE obj)
|
323
|
+
{
|
324
|
+
DataViewAset(obj);
|
325
|
+
rb_type_array_set_uint16(buf->buf, index, (unsigned short)NUM2INT(item), little_endian);
|
326
|
+
return Qnil;
|
327
|
+
}
|
328
|
+
|
329
|
+
/*
|
330
|
+
* call-seq:
|
331
|
+
* view.get_uint16(2) => Fixnum
|
332
|
+
*
|
333
|
+
* Gets an unsigned int16 value from a given offset, using the provided endianness.
|
334
|
+
*
|
335
|
+
* === Examples
|
336
|
+
* buf = ArrayBuffer.new(100) => ArrayBuffer
|
337
|
+
* view = DataView.new(buf) => DataView
|
338
|
+
* view.set_uint16(2, 20) => nil
|
339
|
+
* view.get_uint16(2) => 20
|
340
|
+
*
|
341
|
+
*/
|
342
|
+
static VALUE rb_data_view_get_uint16(int argc, VALUE *argv, VALUE obj)
|
343
|
+
{
|
344
|
+
DataViewAget(obj);
|
345
|
+
return INT2FIX(rb_type_array_get_uint16(buf->buf, index, little_endian));
|
346
|
+
}
|
347
|
+
|
348
|
+
/*
|
349
|
+
* call-seq:
|
350
|
+
* view.set_int32(2, 658) => nil
|
351
|
+
*
|
352
|
+
* Sets an int32 value at a given offset, using the provided endianness.
|
353
|
+
*
|
354
|
+
* === Examples
|
355
|
+
* buf = ArrayBuffer.new(100) => ArrayBuffer
|
356
|
+
* view = DataView.new(buf) => DataView
|
357
|
+
* view.set_int32(2, 758) => nil
|
358
|
+
* view.set_int32(3, -23) => nil
|
359
|
+
*
|
360
|
+
*/
|
361
|
+
static VALUE rb_data_view_set_int32(int argc, VALUE *argv, VALUE obj)
|
362
|
+
{
|
363
|
+
DataViewAset(obj);
|
364
|
+
rb_type_array_set_int32(buf->buf, index, NUM2INT(item), little_endian);
|
365
|
+
return Qnil;
|
366
|
+
}
|
367
|
+
|
368
|
+
/*
|
369
|
+
* call-seq:
|
370
|
+
* view.get_int32(2) => Fixnum
|
371
|
+
*
|
372
|
+
* Gets an int32 value from a given offset, using the provided endianness.
|
373
|
+
*
|
374
|
+
* === Examples
|
375
|
+
* buf = ArrayBuffer.new(100) => ArrayBuffer
|
376
|
+
* view = DataView.new(buf) => DataView
|
377
|
+
* view.set_int32(2, 758) => nil
|
378
|
+
* view.get_int32(2) => 758
|
379
|
+
*
|
380
|
+
*/
|
381
|
+
static VALUE rb_data_view_get_int32(int argc, VALUE *argv, VALUE obj)
|
382
|
+
{
|
383
|
+
DataViewAget(obj);
|
384
|
+
return INT2FIX(rb_type_array_get_int32(buf->buf, index, little_endian));
|
385
|
+
}
|
386
|
+
|
387
|
+
/*
|
388
|
+
* call-seq:
|
389
|
+
* view.set_uint32(2, 20) => nil
|
390
|
+
*
|
391
|
+
* Sets an unsigned int32 value at a given offset, using the provided endianness.
|
392
|
+
*
|
393
|
+
* === Examples
|
394
|
+
* buf = ArrayBuffer.new(100) => ArrayBuffer
|
395
|
+
* view = DataView.new(buf) => DataView
|
396
|
+
* view.set_uint32(2, 758) => nil
|
397
|
+
*
|
398
|
+
*/
|
399
|
+
static VALUE rb_data_view_set_uint32(int argc, VALUE *argv, VALUE obj)
|
400
|
+
{
|
401
|
+
DataViewAset(obj);
|
402
|
+
rb_type_array_set_uint32(buf->buf, index, (unsigned int)NUM2INT(item), little_endian);
|
403
|
+
return Qnil;
|
404
|
+
}
|
405
|
+
|
406
|
+
/*
|
407
|
+
* call-seq:
|
408
|
+
* view.get_uint32(2) => Fixnum
|
409
|
+
*
|
410
|
+
* Gets an unsigned int32 value from a given offset, using the provided endianness.
|
411
|
+
*
|
412
|
+
* === Examples
|
413
|
+
* buf = ArrayBuffer.new(100) => ArrayBuffer
|
414
|
+
* view = DataView.new(buf) => DataView
|
415
|
+
* view.set_uint32(2, 758) => nil
|
416
|
+
* view.get_uint32(2) => 758
|
417
|
+
*
|
418
|
+
*/
|
419
|
+
static VALUE rb_data_view_get_uint32(int argc, VALUE *argv, VALUE obj)
|
420
|
+
{
|
421
|
+
DataViewAget(obj);
|
422
|
+
return INT2FIX(rb_type_array_get_uint32(buf->buf, index, little_endian));
|
423
|
+
}
|
424
|
+
|
425
|
+
/*
|
426
|
+
* call-seq:
|
427
|
+
* view.set_float32(2, 0.775) => nil
|
428
|
+
*
|
429
|
+
* Sets a float32 value at a given offset, using the provided endianness.
|
430
|
+
*
|
431
|
+
* === Examples
|
432
|
+
* buf = ArrayBuffer.new(100) => ArrayBuffer
|
433
|
+
* view = DataView.new(buf) => DataView
|
434
|
+
* view.set_float32(2, 0.775) => nil
|
435
|
+
*
|
436
|
+
*/
|
437
|
+
static VALUE rb_data_view_set_float32(int argc, VALUE *argv, VALUE obj)
|
438
|
+
{
|
439
|
+
float val;
|
440
|
+
DataViewAset(obj);
|
441
|
+
switch (TYPE(item)) {
|
442
|
+
case T_FIXNUM:
|
443
|
+
val = (float)FIX2LONG(item);
|
444
|
+
break;
|
445
|
+
case T_BIGNUM:
|
446
|
+
val = (float)rb_big2dbl(item);
|
447
|
+
break;
|
448
|
+
case T_FLOAT:
|
449
|
+
val = (float)RFLOAT_VALUE(item);
|
450
|
+
break;
|
451
|
+
default:
|
452
|
+
rb_raise(rb_eTypeError, "Type arrays only support Fixnum, Bignum and Float instances");
|
453
|
+
}
|
454
|
+
rb_type_array_set_float32(buf->buf, index, val, little_endian);
|
455
|
+
return Qnil;
|
456
|
+
}
|
457
|
+
|
458
|
+
/*
|
459
|
+
* call-seq:
|
460
|
+
* view.get_float32(2) => Float
|
461
|
+
*
|
462
|
+
* Gets a float32 value from a given offset, using the provided endianness.
|
463
|
+
*
|
464
|
+
* === Examples
|
465
|
+
* buf = ArrayBuffer.new(100) => ArrayBuffer
|
466
|
+
* view = DataView.new(buf) => DataView
|
467
|
+
* view.set_float32(2, 77.643) => nil
|
468
|
+
* view.get_float32(2) => 758
|
469
|
+
*
|
470
|
+
*/
|
471
|
+
static VALUE rb_data_view_get_float32(int argc, VALUE *argv, VALUE obj)
|
472
|
+
{
|
473
|
+
DataViewAget(obj);
|
474
|
+
return rb_float_new((double)rb_type_array_get_float32(buf->buf, index, little_endian));
|
475
|
+
}
|
476
|
+
|
477
|
+
/*
|
478
|
+
* call-seq:
|
479
|
+
* view.set_float64(2, 77.643) => nil
|
480
|
+
*
|
481
|
+
* Sets a float64 value at a given offset, using the provided endianness.
|
482
|
+
*
|
483
|
+
* === Examples
|
484
|
+
* buf = ArrayBuffer.new(100) => ArrayBuffer
|
485
|
+
* view = DataView.new(buf) => DataView
|
486
|
+
* view.set_float64(2, 77.643) => nil
|
487
|
+
*
|
488
|
+
*/
|
489
|
+
static VALUE rb_data_view_set_float64(int argc, VALUE *argv, VALUE obj)
|
490
|
+
{
|
491
|
+
double val;
|
492
|
+
DataViewAset(obj);
|
493
|
+
switch (TYPE(item)) {
|
494
|
+
case T_FIXNUM:
|
495
|
+
val = (double)FIX2LONG(item);
|
496
|
+
break;
|
497
|
+
case T_BIGNUM:
|
498
|
+
val = rb_big2dbl(item);
|
499
|
+
break;
|
500
|
+
case T_FLOAT:
|
501
|
+
val = RFLOAT_VALUE(item);
|
502
|
+
break;
|
503
|
+
default:
|
504
|
+
rb_raise(rb_eTypeError, "Type arrays only support Fixnum, Bignum and Float instances");
|
505
|
+
}
|
506
|
+
rb_type_array_set_float64(buf->buf, index, val, little_endian);
|
507
|
+
return Qnil;
|
508
|
+
}
|
509
|
+
|
510
|
+
/*
|
511
|
+
* call-seq:
|
512
|
+
* view.get_float64(2) => Float
|
513
|
+
*
|
514
|
+
* Gets a float64 value from a given offset, using the provided endianness.
|
515
|
+
*
|
516
|
+
* === Examples
|
517
|
+
* buf = ArrayBuffer.new(100) => ArrayBuffer
|
518
|
+
* view = DataView.new(buf) => DataView
|
519
|
+
* view.set_float64(2, 77.643) => nil
|
520
|
+
* view.get_float64(2) => 758
|
521
|
+
*
|
522
|
+
*/
|
523
|
+
static VALUE rb_data_view_get_float64(int argc, VALUE *argv, VALUE obj)
|
524
|
+
{
|
525
|
+
DataViewAget(obj);
|
526
|
+
return rb_float_new(rb_type_array_get_float64(buf->buf, index, little_endian));
|
527
|
+
}
|
528
|
+
|
529
|
+
/*
|
530
|
+
* call-seq:
|
531
|
+
* view.to_s => String
|
532
|
+
*
|
533
|
+
* Returns a String (binary) representation of the underlying buffer managed by this DataView instance.
|
534
|
+
*
|
535
|
+
* === Examples
|
536
|
+
* buf = ArrayBuffer.new("buffer") => ArrayBuffer
|
537
|
+
* view = DataView.new(buf) => DataView
|
538
|
+
* view.to_s => "buffer"
|
539
|
+
*
|
540
|
+
*/
|
541
|
+
static VALUE rb_data_view_to_s(VALUE obj)
|
542
|
+
{
|
543
|
+
GetDataView(obj);
|
544
|
+
return rb_array_buffer_to_s(view->buf);
|
545
|
+
}
|
546
|
+
|
547
|
+
void _init_data_view()
|
548
|
+
{
|
549
|
+
rb_cDataView = rb_define_class("DataView", rb_cObject);
|
550
|
+
|
551
|
+
rb_define_singleton_method(rb_cDataView, "new", rb_data_view_s_new, -1);
|
552
|
+
rb_define_method(rb_cDataView, "byte_length", rb_data_view_byte_length, 0);
|
553
|
+
rb_define_method(rb_cDataView, "byte_offset", rb_data_view_byte_offset, 0);
|
554
|
+
rb_define_method(rb_cDataView, "buffer", rb_data_view_buffer, 0);
|
555
|
+
rb_define_method(rb_cDataView, "to_s", rb_data_view_to_s, 0);
|
556
|
+
|
557
|
+
rb_define_method(rb_cDataView, "set_int8", rb_data_view_set_int8, 2);
|
558
|
+
rb_define_method(rb_cDataView, "set_uint8", rb_data_view_set_uint8, 2);
|
559
|
+
rb_define_method(rb_cDataView, "set_int16", rb_data_view_set_int16, -1);
|
560
|
+
rb_define_method(rb_cDataView, "set_uint16", rb_data_view_set_uint16, -1);
|
561
|
+
rb_define_method(rb_cDataView, "set_int32", rb_data_view_set_int32, -1);
|
562
|
+
rb_define_method(rb_cDataView, "set_uint32", rb_data_view_set_uint32, -1);
|
563
|
+
rb_define_method(rb_cDataView, "set_float32", rb_data_view_set_float32, -1);
|
564
|
+
rb_define_method(rb_cDataView, "set_float64", rb_data_view_set_float64, -1);
|
565
|
+
|
566
|
+
rb_define_method(rb_cDataView, "get_int8", rb_data_view_get_int8, 1);
|
567
|
+
rb_define_method(rb_cDataView, "get_uint8", rb_data_view_get_uint8, 1);
|
568
|
+
rb_define_method(rb_cDataView, "get_int16", rb_data_view_get_int16, -1);
|
569
|
+
rb_define_method(rb_cDataView, "get_uint16", rb_data_view_get_uint16, -1);
|
570
|
+
rb_define_method(rb_cDataView, "get_int32", rb_data_view_get_int32, -1);
|
571
|
+
rb_define_method(rb_cDataView, "get_uint32", rb_data_view_get_uint32, -1);
|
572
|
+
rb_define_method(rb_cDataView, "get_float32", rb_data_view_get_float32, -1);
|
573
|
+
rb_define_method(rb_cDataView, "get_float64", rb_data_view_get_float64, -1);
|
574
|
+
}
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#ifndef DATA_VIEW_H
|
2
|
+
#define DATA_VIEW_H
|
3
|
+
|
4
|
+
typedef struct {
|
5
|
+
unsigned long byte_length;
|
6
|
+
unsigned long byte_offset;
|
7
|
+
VALUE buf;
|
8
|
+
} rb_data_view_t;
|
9
|
+
|
10
|
+
#define GetDataView(obj) \
|
11
|
+
rb_data_view_t *view = NULL; \
|
12
|
+
Data_Get_Struct(obj, rb_data_view_t, view); \
|
13
|
+
if (!view) rb_raise(rb_eTypeError, "uninitialized DataView!");
|
14
|
+
|
15
|
+
#define DataViewAset(obj) \
|
16
|
+
VALUE offset, item, little_endian; \
|
17
|
+
unsigned long index; \
|
18
|
+
GetDataView(obj); \
|
19
|
+
GetArrayBuffer(view->buf); \
|
20
|
+
rb_scan_args(argc, argv, "21", &offset, &item, &little_endian); \
|
21
|
+
if (NIL_P(little_endian)) little_endian = Qfalse; \
|
22
|
+
index = rb_data_view_assert_offset(view, offset);
|
23
|
+
|
24
|
+
#define DataViewAget(obj) \
|
25
|
+
VALUE offset, little_endian; \
|
26
|
+
unsigned long index; \
|
27
|
+
GetDataView(obj); \
|
28
|
+
GetArrayBuffer(view->buf); \
|
29
|
+
rb_scan_args(argc, argv, "11", &offset, &little_endian); \
|
30
|
+
if (NIL_P(little_endian)) little_endian = Qfalse; \
|
31
|
+
index = rb_data_view_assert_offset(view, offset);
|
32
|
+
|
33
|
+
void _init_data_view();
|
34
|
+
|
35
|
+
#endif
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'mkmf'
|
4
|
+
|
5
|
+
RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
|
6
|
+
|
7
|
+
dir_config('type_array')
|
8
|
+
|
9
|
+
have_func('rb_thread_blocking_region')
|
10
|
+
|
11
|
+
$CFLAGS << ' -Wall -funroll-loops'
|
12
|
+
$CFLAGS << ' -Wextra -O0 -ggdb3' if ENV['DEBUG']
|
13
|
+
|
14
|
+
create_makefile('type_array_ext')
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#ifndef TYPE_ARRAY_PRELUDE_H
|
2
|
+
#define TYPE_ARRAY_PRELUDE_H
|
3
|
+
#include <stdint.h>
|
4
|
+
|
5
|
+
#define TYPE_ARRAY_IS_LITTLE_ENDIAN (*(uint16_t*)"\0\1">>8) ? Qtrue : Qfalse
|
6
|
+
|
7
|
+
#ifndef RFLOAT_VALUE
|
8
|
+
#define RFLOAT_VALUE(v) (RFLOAT(v)->value)
|
9
|
+
#endif
|
10
|
+
|
11
|
+
#ifdef RUBINIUS
|
12
|
+
#include "rubinius.h"
|
13
|
+
#else
|
14
|
+
#ifdef JRUBY
|
15
|
+
#include "jruby.h"
|
16
|
+
#else
|
17
|
+
#ifdef HAVE_RB_THREAD_BLOCKING_REGION
|
18
|
+
#include "ruby19.h"
|
19
|
+
#else
|
20
|
+
#include "ruby18.h"
|
21
|
+
#endif
|
22
|
+
#endif
|
23
|
+
#endif
|
24
|
+
|
25
|
+
#endif
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#ifndef TYPE_ARRAY_RUBINIUS_H
|
2
|
+
#define TYPE_ARRAY_RUBINIUS_H
|
3
|
+
|
4
|
+
#define RSTRING_NOT_MODIFIED
|
5
|
+
|
6
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
7
|
+
#include <ruby/encoding.h>
|
8
|
+
extern rb_encoding *binary_encoding;
|
9
|
+
#define ArrayBufferEncode(str) rb_enc_associate(str, binary_encoding)
|
10
|
+
#else
|
11
|
+
#define ArrayBufferEncode(str) str
|
12
|
+
#endif
|
13
|
+
|
14
|
+
#define TRAP_BEG
|
15
|
+
#define TRAP_END
|
16
|
+
|
17
|
+
#define FIXNUM_FLAG 0x01
|
18
|
+
|
19
|
+
#endif
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#ifndef TYPE_ARRAY_RUBY18_H
|
2
|
+
#define TYPE_ARRAY_RUBY18_H
|
3
|
+
|
4
|
+
#define ArrayBufferEncode(str) str
|
5
|
+
|
6
|
+
#ifndef RSTRING_PTR
|
7
|
+
#define RSTRING_PTR(str) RSTRING(str)->ptr
|
8
|
+
#endif
|
9
|
+
#ifndef RSTRING_LEN
|
10
|
+
#define RSTRING_LEN(s) (RSTRING(s)->len)
|
11
|
+
#endif
|
12
|
+
|
13
|
+
#include "rubysig.h"
|
14
|
+
|
15
|
+
#endif
|