type_array 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,540 @@
1
+ #include "type_array_ext.h"
2
+
3
+ /*
4
+ * :nodoc:
5
+ * Provides a typed interface to a given ArrayBuffer instance. Values will only be coerced according to the type of
6
+ * array. Currently coercing to and from Ruby objects are handled through callbacks via function pointers. This may
7
+ * change in the short term.
8
+ *
9
+ */
10
+
11
+ VALUE rb_cTypeArray;
12
+
13
+ VALUE rb_cInt8Array;
14
+ VALUE rb_cUInt8Array;
15
+ VALUE rb_cInt16Array;
16
+ VALUE rb_cUInt16Array;
17
+ VALUE rb_cInt32Array;
18
+ VALUE rb_cUInt32Array;
19
+ VALUE rb_cFloat32Array;
20
+ VALUE rb_cFloat64Array;
21
+
22
+ static ID rb_type_array_intern_aget;
23
+ static ID rb_type_array_intern_aset;
24
+
25
+ /*
26
+ * :nodoc:
27
+ * Coerces a Ruby object to an int8 at a given offset, according to host endianness.
28
+ *
29
+ */
30
+ DefineTypeArraySetter(int8, (signed char)NUM2CHR(item));
31
+
32
+ /*
33
+ * :nodoc:
34
+ * Coerces an int8 at a given offset to a Ruby object, according to host endianness.
35
+ *
36
+ */
37
+ DefineTypeArrayGetter(int8, signed char, TACHR2FIX(val));
38
+
39
+ /*
40
+ * :nodoc:
41
+ * Coerces a Ruby object to an unsigned int8 at a given offset, according to host endianness.
42
+ *
43
+ */
44
+ DefineTypeArraySetter(uint8, (unsigned char)NUM2CHR(item));
45
+
46
+ /*
47
+ * :nodoc:
48
+ * Coerces an unsigned int8 at a given offset to a Ruby object, according to host endianness.
49
+ *
50
+ */
51
+ DefineTypeArrayGetter(uint8, unsigned char, TACHR2FIX(val));
52
+
53
+ /*
54
+ * :nodoc:
55
+ * Coerces a Ruby object to an int16 at a given offset, according to host endianness.
56
+ *
57
+ */
58
+ DefineTypeArraySetter(int16, (short)NUM2INT(item));
59
+
60
+ /*
61
+ * :nodoc:
62
+ * Coerces an int16 at a given offset to a Ruby object, according to host endianness.
63
+ *
64
+ */
65
+ DefineTypeArrayGetter(int16, short, INT2FIX(val));
66
+
67
+ /*
68
+ * :nodoc:
69
+ * Coerces a Ruby object to an unsigned int16 at a given offset, according to host endianness.
70
+ *
71
+ */
72
+ DefineTypeArraySetter(uint16, (unsigned short)NUM2INT(item));
73
+
74
+ /*
75
+ * :nodoc:
76
+ * Coerces an unsigned int16 at a given offset to a Ruby object, according to host endianness.
77
+ *
78
+ */
79
+ DefineTypeArrayGetter(uint16, unsigned short, INT2FIX(val));
80
+
81
+ /*
82
+ * :nodoc:
83
+ * Coerces a Ruby object to an int32 at a given offset, according to host endianness.
84
+ *
85
+ */
86
+ DefineTypeArraySetter(int32, NUM2INT(item));
87
+
88
+ /*
89
+ * :nodoc:
90
+ * Coerces an int32 at a given offset to a Ruby object, according to host endianness.
91
+ *
92
+ */
93
+ DefineTypeArrayGetter(int32, int, INT2FIX(val));
94
+
95
+ /*
96
+ * :nodoc:
97
+ * Coerces a Ruby object to an unsigned int32 at a given offset, according to host endianness.
98
+ *
99
+ */
100
+ DefineTypeArraySetter(uint32, NUM2UINT(item));
101
+
102
+ /*
103
+ * :nodoc:
104
+ * Coerces an unsigned int32 at a given offset to a Ruby object, according to host endianness.
105
+ *
106
+ */
107
+ DefineTypeArrayGetter(uint32, unsigned int, UINT2NUM(val));
108
+
109
+ /*
110
+ * :nodoc:
111
+ * Coerces a Ruby object to a float32 (float) at a given offset, according to host endianness.
112
+ *
113
+ */
114
+ static void rb_type_array_aset_float32(rb_array_buffer_t *buf, long index, VALUE item)
115
+ {
116
+ float val;
117
+ switch (TYPE(item)) {
118
+ case T_FIXNUM:
119
+ val = (float)FIX2LONG(item);
120
+ break;
121
+ case T_BIGNUM:
122
+ val = (float)rb_big2dbl(item);
123
+ break;
124
+ case T_FLOAT:
125
+ val = (float)RFLOAT_VALUE(item);
126
+ break;
127
+ default:
128
+ rb_raise(rb_eTypeError, "Type arrays only support Fixnum, Bignum and Float instances");
129
+ }
130
+ rb_type_array_set_float32(buf, index, val, TYPE_ARRAY_IS_LITTLE_ENDIAN);
131
+ }
132
+
133
+ /*
134
+ * :nodoc:
135
+ * Coerces a float32 (float) at a given offset to a Ruby object, according to host endianness.
136
+ *
137
+ */
138
+ DefineTypeArrayGetter(float32, float, rb_float_new((double)val));
139
+
140
+ /*
141
+ * :nodoc:
142
+ * Coerces a Ruby object to a float64 (double) at a given offset, according to host endianness.
143
+ *
144
+ */
145
+ static void rb_type_array_aset_float64(rb_array_buffer_t *buf, long index, VALUE item)
146
+ {
147
+ double val;
148
+ switch (TYPE(item)) {
149
+ case T_FIXNUM:
150
+ val = FIX2LONG(item);
151
+ break;
152
+ case T_BIGNUM:
153
+ val = rb_big2dbl(item);
154
+ break;
155
+ case T_FLOAT:
156
+ val = RFLOAT_VALUE(item);
157
+ break;
158
+ default:
159
+ rb_raise(rb_eTypeError, "Type arrays only support Fixnum, Bignum and Float instances");
160
+ }
161
+ rb_type_array_set_float64(buf, index, val, TYPE_ARRAY_IS_LITTLE_ENDIAN);
162
+ }
163
+
164
+ /*
165
+ * :nodoc:
166
+ * Coerces a float64 (double) at a given offset to a Ruby object, according to host endianness.
167
+ *
168
+ */
169
+ DefineTypeArrayGetter(float64, double, rb_float_new(val));
170
+
171
+ /*
172
+ * :nodoc:
173
+ * Asserts type alignment.
174
+ *
175
+ */
176
+ inline int rb_type_array_assert_alignment(unsigned long val, unsigned long bytes) {
177
+ return (val & (bytes - 1)) == 0 ? 1 : 0;
178
+ }
179
+
180
+ /*
181
+ * :nodoc:
182
+ * Swizzles byte order.
183
+ *
184
+ */
185
+ inline void rb_type_array_swizzle(char* buf, unsigned long len) {
186
+ unsigned long i;
187
+ for (i = 0; i < len / 2; ++i) {
188
+ char t = buf[i];
189
+ buf[i] = buf[len - i - 1];
190
+ buf[len - i - 1] = t;
191
+ }
192
+ }
193
+
194
+ /*
195
+ * :nodoc:
196
+ * Validates offset boundaries.
197
+ *
198
+ */
199
+ static inline long rb_type_array_assert_offset(rb_type_array_t *ary, VALUE idx)
200
+ {
201
+ long index;
202
+ Check_Type(idx, T_FIXNUM);
203
+ index = FIX2LONG(idx) * ary->size;
204
+ if (index < 0) rb_raise(rb_eRangeError, "Offset may not be negative.");
205
+ if (!rb_type_array_assert_alignment(index, ary->size)) rb_raise(rb_eRangeError, "Byte offset is not aligned.");
206
+ if ((unsigned long)index > ary->byte_length) rb_raise(rb_eRangeError, "Offset out of range.");
207
+ if (ary->size > (ary->byte_length - (unsigned long)index)) rb_raise(rb_eRangeError, "Offset/length out of range.");
208
+ return index;
209
+ }
210
+
211
+ /*
212
+ * :nodoc:
213
+ * GC mark callback
214
+ *
215
+ */
216
+ static void rb_mark_type_array(void *ptr)
217
+ {
218
+ rb_type_array_t *ary = (rb_type_array_t *)ptr;
219
+ if (ary) rb_gc_mark(ary->buf);
220
+ }
221
+
222
+ /*
223
+ * :nodoc:
224
+ * GC free callback
225
+ *
226
+ */
227
+ static void rb_free_type_array(void *ptr)
228
+ {
229
+ rb_type_array_t *ary = (rb_type_array_t *)ptr;
230
+ #ifdef TYPE_ARRAY_DEBUG
231
+ printf(">> rb_free_type_array %p\n", ptr);
232
+ #endif
233
+ if (ary) {
234
+ xfree(ary);
235
+ ary = NULL;
236
+ }
237
+ #ifdef TYPE_ARRAY_DEBUG
238
+ printf("<< rb_free_type_array %p\n", ptr);
239
+ #endif
240
+ }
241
+
242
+ /*
243
+ * call-seq:
244
+ * Int32Array.new(100) => Int32Array
245
+ * Int32Array.new("01234567") => Int32Array
246
+ * Int32Array.new(buf, 20) => Int32Array
247
+ * Int32Array.new(buf, 0, 20) => Int32Array
248
+ * Int32Array.new(buf, 20, 20) => Int32Array
249
+ *
250
+ * Creates a new TypeArray instance. ArrayBuffer, data (String) and length constructors are supported.
251
+ *
252
+ * === Examples
253
+ * buf = ArrayBuffer.new(100) => ArrayBuffer
254
+ *
255
+ * ary = Int32Array.new(buf, 20) => Int32Array
256
+ * ary.length => 20
257
+ * ary.byte_length => 80
258
+ * ary.byte_offset => 20
259
+ *
260
+ * ary = Int32Array.new(buf, 0, 20) => Int32Array
261
+ * ary.length => 20
262
+ * ary.byte_length => 80
263
+ * ary.byte_offset => 0
264
+ *
265
+ * ary = Int32Array.new(buf, 20, 20) => Int32Array
266
+ * ary.length => 20
267
+ * ary.byte_length => 80
268
+ * ary.byte_offset => 20
269
+ *
270
+ * ary = Int32Array.new("01234567") => Int32Array
271
+ * ary.byte_length => 8
272
+ * ary.to_s => "01234567"
273
+ *
274
+ * ary = Int32Array.new(100) => Int32Array
275
+ * ary.length => 100
276
+ * ary.byte_length => 400
277
+ */
278
+ static VALUE rb_type_array_s_new(int argc, VALUE *argv, VALUE klass)
279
+ {
280
+ VALUE type_array;
281
+ VALUE obj, byte_offset, length;
282
+ rb_type_array_t *array = NULL;
283
+ unsigned long buffer_length, offset;
284
+ if (klass == rb_cTypeArray) rb_raise(rb_eTypeError, "TypeArray cannot be instantiated directly.");
285
+ rb_scan_args(argc, argv, "12", &obj, &byte_offset, &length);
286
+ type_array = Data_Make_Struct(klass, rb_type_array_t, rb_mark_type_array, rb_free_type_array, array);
287
+ array->size = FIX2ULONG(rb_const_get(klass, rb_intern("BYTES_PER_ELEMENT")));
288
+ array->byte_offset = 0;
289
+ array->length = 0;
290
+
291
+ if (klass == rb_cInt8Array) {
292
+ array->aref_fn = rb_type_array_aref_int8;
293
+ array->aset_fn = rb_type_array_aset_int8;
294
+ } else if (klass == rb_cUInt8Array) {
295
+ array->aref_fn = rb_type_array_aref_uint8;
296
+ array->aset_fn = rb_type_array_aset_uint8;
297
+ } else if (klass == rb_cInt16Array) {
298
+ array->aref_fn = rb_type_array_aref_int16;
299
+ array->aset_fn = rb_type_array_aset_int16;
300
+ } else if (klass == rb_cUInt16Array) {
301
+ array->aref_fn = rb_type_array_aref_uint16;
302
+ array->aset_fn = rb_type_array_aset_uint16;
303
+ } else if (klass == rb_cInt32Array) {
304
+ array->aref_fn = rb_type_array_aref_int32;
305
+ array->aset_fn = rb_type_array_aset_int32;
306
+ } else if (klass == rb_cUInt32Array) {
307
+ array->aref_fn = rb_type_array_aref_uint32;
308
+ array->aset_fn = rb_type_array_aset_uint32;
309
+ } else if (klass == rb_cFloat32Array) {
310
+ array->aref_fn = rb_type_array_aref_float32;
311
+ array->aset_fn = rb_type_array_aset_float32;
312
+ } else if (klass == rb_cFloat64Array) {
313
+ array->aref_fn = rb_type_array_aref_float64;
314
+ array->aset_fn = rb_type_array_aset_float64;
315
+ }
316
+
317
+ if (FIXNUM_P(obj)) {
318
+ array->length = FIX2ULONG(obj);
319
+ array->byte_length = (array->length * array->size);
320
+ array->buf = rb_alloc_array_buffer(array->byte_length, NULL);
321
+ } else if (rb_type(obj) == T_STRING) {
322
+ array->byte_length = (unsigned long)RSTRING_LEN(obj);
323
+ array->length = (array->byte_length / array->size);
324
+ ArrayBufferEncode(obj);
325
+ array->buf = rb_alloc_array_buffer(array->byte_length, (void *)RSTRING_PTR(obj));
326
+ } else if (rb_class_of(obj) == rb_cArrayBuffer) {
327
+ GetArrayBuffer(obj);
328
+ if (!NIL_P(byte_offset)) {
329
+ Check_Type(byte_offset, T_FIXNUM);
330
+ array->byte_offset = FIX2ULONG(byte_offset);
331
+ if (!rb_type_array_assert_alignment(array->byte_offset, array->size))
332
+ rb_raise(rb_eRangeError, "Byte offset is not aligned.");
333
+ }
334
+ buffer_length = buf->length;
335
+ if (!NIL_P(length)) {
336
+ Check_Type(length, T_FIXNUM);
337
+ array->length = FIX2ULONG(length);
338
+ array->byte_length = array->length * array->size;
339
+ } else {
340
+ array->byte_length = buffer_length - array->byte_offset;
341
+ }
342
+ if ((array->byte_offset + array->byte_length) > buffer_length)
343
+ rb_raise(rb_eRangeError, "Byte offset / length is not aligned.");
344
+ if (array->length == 0) array->length = array->byte_length / array->size;
345
+ if (array->byte_offset > buffer_length || array->byte_offset + array->length > buffer_length ||
346
+ array->byte_offset + array->length * array->size > buffer_length) {
347
+ rb_raise(rb_eRangeError, "Length is out of range.");
348
+ }
349
+ array->buf = obj;
350
+ } else if (rb_obj_is_kind_of(obj, rb_cTypeArray) == Qtrue) {
351
+ GetTypeArray(obj);
352
+ array->length = ary->length;
353
+ array->byte_length = (array->size * array->length);
354
+ array->buf = rb_alloc_array_buffer(array->byte_length, NULL);
355
+ array->byte_offset = 0;
356
+ for (offset = 0; offset < array->length; ++offset) {
357
+ VALUE offs = INT2FIX(offset);
358
+ VALUE val = rb_funcall(obj, rb_type_array_intern_aget, 1, offs);
359
+ rb_funcall(type_array, rb_type_array_intern_aset, 2, offs, val);
360
+ }
361
+ } else {
362
+ rb_raise(rb_eTypeError, "TypeArray constructor %s not supported.", RSTRING_PTR(rb_obj_as_string(obj)));
363
+ }
364
+ rb_obj_call_init(type_array, 0, NULL);
365
+ return type_array;
366
+ }
367
+
368
+ /*
369
+ * call-seq:
370
+ * ary.byte_length => Fixnum
371
+ *
372
+ * Returns the size of the underlying buffer managed by this TypeArray instance.
373
+ *
374
+ * === Examples
375
+ * ary = Int32Array.new("01234567") => Int32Array
376
+ * ary.byte_length => 8
377
+ *
378
+ */
379
+ static VALUE rb_type_array_byte_length(VALUE obj)
380
+ {
381
+ GetTypeArray(obj);
382
+ return ULONG2NUM(ary->byte_length);
383
+ }
384
+
385
+ /*
386
+ * call-seq:
387
+ * ary.length => Fixnum
388
+ *
389
+ * Returns the max number of elements this typed array instance can accommodate.
390
+ *
391
+ * === Examples
392
+ * ary = Int32Array.new("01234567") => Int32Array
393
+ * ary.byte_length => 8
394
+ * ary.length => 2
395
+ *
396
+ */
397
+ static VALUE rb_type_array_length(VALUE obj)
398
+ {
399
+ GetTypeArray(obj);
400
+ return ULONG2NUM(ary->length);
401
+ }
402
+
403
+ /*
404
+ * call-seq:
405
+ * ary.buffer => String
406
+ *
407
+ * Returns the underlying buffer managed by this ArrayBuffer instance.
408
+ *
409
+ * === Examples
410
+ * ary = Int32Array.new("buffer") => DataView
411
+ * ary.buffer => ArrayBuffer
412
+ *
413
+ */
414
+ static VALUE rb_type_array_buffer(VALUE obj)
415
+ {
416
+ GetTypeArray(obj);
417
+ return ary->buf;
418
+ }
419
+
420
+ /*
421
+ * call-seq:
422
+ * art.to_s => String
423
+ *
424
+ * Returns a String (binary) representation of the underlying buffer managed by this TypeArray instance.
425
+ *
426
+ * === Examples
427
+ * buf = ArrayBuffer.new("buffer") => ArrayBuffer
428
+ * ary = Int32Array.new(buf) => Int32Array
429
+ * ary.to_s => "buffer"
430
+ *
431
+ */
432
+ static VALUE rb_type_array_to_s(VALUE obj)
433
+ {
434
+ GetTypeArray(obj);
435
+ return rb_array_buffer_to_s(ary->buf);
436
+ }
437
+
438
+ /*
439
+ * call-seq:
440
+ * ary.byte_offset => Fixnum
441
+ *
442
+ * Returns the offset into the underlying buffer managed by this TypeArray instance.
443
+ *
444
+ * === Examples
445
+ * ary = Int32Array.new("01234567") => Int32Array
446
+ * ary.byte_offset => 0
447
+ *
448
+ * ary = Int32Array.new("01234567", 2) => Int32Array
449
+ * ary.byte_offset => 2
450
+ *
451
+ */
452
+ static VALUE rb_type_array_byte_offset(VALUE obj)
453
+ {
454
+ GetTypeArray(obj);
455
+ return ULONG2NUM(ary->byte_offset);
456
+ }
457
+
458
+ /*
459
+ * call-seq:
460
+ * ary[1] = 20 => nil
461
+ *
462
+ * Sets a value at a given offset, with coercion dependent on the array type of this instance.
463
+ *
464
+ * === Examples
465
+ * ary = Int32Array.new("01234567") => Int32Array
466
+ * ary[1] = 23 => nil
467
+ *
468
+ */
469
+ static VALUE rb_type_array_aset(VALUE obj, VALUE idx, VALUE item)
470
+ {
471
+ GetTypeArray(obj);
472
+ GetArrayBuffer(ary->buf);
473
+ long index = rb_type_array_assert_offset(ary, idx);
474
+ switch (TYPE(item)) {
475
+ case T_FIXNUM:
476
+ case T_BIGNUM:
477
+ case T_FLOAT:
478
+ break;
479
+ default:
480
+ rb_raise(rb_eTypeError, "Type arrays only support Fixnum, Bignum and Float instances");
481
+ }
482
+ ary->aset_fn(buf->buf, index, item);
483
+ return Qnil;
484
+ }
485
+
486
+ /*
487
+ * call-seq:
488
+ * ary[1] => Fixnum, Bignum or Float
489
+ *
490
+ * Gets a value at a given offset, with coercion dependent on the array type of this instance.
491
+ *
492
+ * === Examples
493
+ * ary = Int32Array.new("01234567") => Int32Array
494
+ * ary[1] = 23 => nil
495
+ * ary[1] => 23
496
+ *
497
+ */
498
+ static VALUE rb_type_array_aget(VALUE obj, VALUE idx)
499
+ {
500
+ GetTypeArray(obj);
501
+ GetArrayBuffer(ary->buf);
502
+ long index = rb_type_array_assert_offset(ary, idx);
503
+ return ary->aref_fn(buf->buf, index);
504
+ }
505
+
506
+ void _init_type_array()
507
+ {
508
+ rb_cTypeArray = rb_define_class("TypeArray", rb_cObject);
509
+
510
+ rb_type_array_intern_aget = rb_intern("[]");
511
+ rb_type_array_intern_aset = rb_intern("[]=");
512
+
513
+ rb_cInt8Array = rb_define_class("Int8Array", rb_cTypeArray);
514
+ rb_cUInt8Array = rb_define_class("UInt8Array", rb_cTypeArray);
515
+ rb_cInt16Array = rb_define_class("Int16Array", rb_cTypeArray);
516
+ rb_cUInt16Array = rb_define_class("UInt16Array", rb_cTypeArray);
517
+ rb_cInt32Array = rb_define_class("Int32Array", rb_cTypeArray);
518
+ rb_cUInt32Array = rb_define_class("UInt32Array", rb_cTypeArray);
519
+ rb_cFloat32Array = rb_define_class("Float32Array", rb_cTypeArray);
520
+ rb_cFloat64Array = rb_define_class("Float64Array", rb_cTypeArray);
521
+
522
+ rb_define_const(rb_cInt8Array, "BYTES_PER_ELEMENT", ULONG2NUM(sizeof(signed char)));
523
+ rb_define_const(rb_cUInt8Array, "BYTES_PER_ELEMENT", ULONG2NUM(sizeof(unsigned char)));
524
+ rb_define_const(rb_cInt16Array, "BYTES_PER_ELEMENT", ULONG2NUM(sizeof(short)));
525
+ rb_define_const(rb_cUInt16Array, "BYTES_PER_ELEMENT", ULONG2NUM(sizeof(unsigned short)));
526
+ rb_define_const(rb_cInt32Array, "BYTES_PER_ELEMENT", ULONG2NUM(sizeof(int)));
527
+ rb_define_const(rb_cUInt32Array, "BYTES_PER_ELEMENT", ULONG2NUM(sizeof(unsigned int)));
528
+ rb_define_const(rb_cFloat32Array, "BYTES_PER_ELEMENT", ULONG2NUM(sizeof(float)));
529
+ rb_define_const(rb_cFloat64Array, "BYTES_PER_ELEMENT", ULONG2NUM(sizeof(double)));
530
+
531
+ rb_define_singleton_method(rb_cTypeArray, "new", rb_type_array_s_new, -1);
532
+
533
+ rb_define_method(rb_cTypeArray, "byte_length", rb_type_array_byte_length, 0);
534
+ rb_define_method(rb_cTypeArray, "length", rb_type_array_length, 0);
535
+ rb_define_method(rb_cTypeArray, "buffer", rb_type_array_buffer, 0);
536
+ rb_define_method(rb_cTypeArray, "byte_offset", rb_type_array_byte_offset, 0);
537
+ rb_define_method(rb_cTypeArray, "to_s", rb_type_array_to_s, 0);
538
+ rb_define_method(rb_cTypeArray, "[]=", rb_type_array_aset, 2);
539
+ rb_define_method(rb_cTypeArray, "[]", rb_type_array_aget, 1);
540
+ }
@@ -0,0 +1,38 @@
1
+ #ifndef TYPE_ARRAY_H
2
+ #define TYPE_ARRAY_H
3
+
4
+ typedef void (type_array_aset_fn) (rb_array_buffer_t *buf, long index, VALUE item);
5
+ typedef VALUE (type_array_aref_fn) (rb_array_buffer_t *buf, long index);
6
+
7
+ typedef struct {
8
+ unsigned long size;
9
+ unsigned long length;
10
+ unsigned long byte_length;
11
+ unsigned long byte_offset;
12
+ type_array_aset_fn *aset_fn;
13
+ type_array_aref_fn *aref_fn;
14
+ VALUE buf;
15
+ } rb_type_array_t;
16
+
17
+ #define GetTypeArray(obj) \
18
+ rb_type_array_t *ary = NULL; \
19
+ Data_Get_Struct(obj, rb_type_array_t, ary); \
20
+ if (!ary) rb_raise(rb_eTypeError, "uninitialized TypeArray!");
21
+
22
+ void rb_type_array_swizzle(char* buf, unsigned long len);
23
+ void _init_type_array();
24
+
25
+ #define DefineTypeArraySetter(name, coercion) \
26
+ void rb_type_array_aset_##name(rb_array_buffer_t *buf, long index, VALUE item) \
27
+ { \
28
+ rb_type_array_set_##name(buf, index, coercion, TYPE_ARRAY_IS_LITTLE_ENDIAN); \
29
+ }
30
+
31
+ #define DefineTypeArrayGetter(name, type, coercion) \
32
+ VALUE rb_type_array_aref_##name(rb_array_buffer_t *buf, long index) \
33
+ { \
34
+ type val = rb_type_array_get_##name(buf, index, TYPE_ARRAY_IS_LITTLE_ENDIAN); \
35
+ return coercion; \
36
+ }
37
+
38
+ #endif
@@ -0,0 +1,25 @@
1
+ #include "type_array_ext.h"
2
+
3
+ #ifdef HAVE_RUBY_ENCODING_H
4
+ rb_encoding *binary_encoding;
5
+ #endif
6
+
7
+ DefineTypeAccessor(int8, signed char);
8
+ DefineTypeAccessor(uint8, unsigned char);
9
+ DefineTypeAccessor(int16, short);
10
+ DefineTypeAccessor(uint16, unsigned short);
11
+ DefineTypeAccessor(int32, int);
12
+ DefineTypeAccessor(uint32, unsigned int);
13
+ DefineTypeAccessor(float32, float);
14
+ DefineTypeAccessor(float64, double);
15
+
16
+ void Init_type_array_ext()
17
+ {
18
+ #ifdef HAVE_RUBY_ENCODING_H
19
+ binary_encoding = rb_enc_find("binary");
20
+ #endif
21
+
22
+ _init_array_buffer();
23
+ _init_type_array();
24
+ _init_data_view();
25
+ }
@@ -0,0 +1,71 @@
1
+ #ifndef TYPE_ARRAY_EXT_H
2
+ #define TYPE_ARRAY_EXT_H
3
+
4
+ #include "ruby.h"
5
+ #include "prelude.h"
6
+
7
+ extern VALUE rb_cArrayBuffer;
8
+
9
+ extern VALUE rb_cTypeArray;
10
+ extern VALUE rb_cInt8Array;
11
+ extern VALUE rb_cUInt8Array;
12
+ extern VALUE rb_cInt16Array;
13
+ extern VALUE rb_cUInt16Array;
14
+ extern VALUE rb_cInt32Array;
15
+ extern VALUE rb_cUInt32Array;
16
+ extern VALUE rb_cInt64Array;
17
+ extern VALUE rb_cUInt64Array;
18
+
19
+ extern VALUE rb_cDataView;
20
+
21
+ /* Special case overrides as the Ruby specific implementations casts to long (thx James Tucker) */
22
+ #define TAINT2FIX(i) ((VALUE)(((char)(i))<<1 | FIXNUM_FLAG))
23
+ #define TACHR2FIX(x) TAINT2FIX((char)((x)&0xff))
24
+
25
+ void rb_type_array_set_int8(void *abuf, unsigned long index, signed char val, VALUE swiz);
26
+ void rb_type_array_set_uint8(void *abuf, unsigned long index, unsigned char val, VALUE swiz);
27
+ void rb_type_array_set_int16(void *abuf, unsigned long index, short val, VALUE swiz);
28
+ void rb_type_array_set_uint16(void *abuf, unsigned long index, unsigned short val, VALUE swiz);
29
+ void rb_type_array_set_int32(void *abuf, unsigned long index, int val, VALUE swiz);
30
+ void rb_type_array_set_uint32(void *abuf, unsigned long index, unsigned int val, VALUE swiz);
31
+ void rb_type_array_set_float32(void *abuf, unsigned long index, float val, VALUE swiz);
32
+ void rb_type_array_set_float64(void *abuf, unsigned long index, double val, VALUE swiz);
33
+
34
+ signed char rb_type_array_get_int8(void *abuf, unsigned long index, VALUE swiz);
35
+ unsigned char rb_type_array_get_uint8(void *abuf, unsigned long index, VALUE swiz);
36
+ short rb_type_array_get_int16(void *abuf, unsigned long index, VALUE swiz);
37
+ unsigned short rb_type_array_get_uint16(void *abuf, unsigned long index, VALUE swiz);
38
+ int rb_type_array_get_int32(void *abuf, unsigned long index, VALUE swiz);
39
+ unsigned int rb_type_array_get_uint32(void *abuf, unsigned long index, VALUE swiz);
40
+ float rb_type_array_get_float32(void *abuf, unsigned long index, VALUE swiz);
41
+ double rb_type_array_get_float64(void *abuf, unsigned long index, VALUE swiz);
42
+
43
+ #define DefineTypeGetter(name, type) \
44
+ inline type rb_type_array_get_##name(void *abuf, unsigned long index, VALUE swiz) \
45
+ { \
46
+ char buf[sizeof(type)]; \
47
+ type val; \
48
+ memmove(buf, (char *)abuf + index, sizeof(type)); \
49
+ if (swiz) rb_type_array_swizzle(buf, sizeof(type)); \
50
+ memmove(&val, buf, sizeof(type)); \
51
+ return val; \
52
+ }
53
+
54
+ #define DefineTypeSetter(name, type) \
55
+ inline void rb_type_array_set_##name(void *abuf, unsigned long index, type val, VALUE swiz) \
56
+ { \
57
+ char buf[sizeof(type)]; \
58
+ memmove(buf, &val, sizeof(type)); \
59
+ if (swiz) rb_type_array_swizzle(buf, sizeof(type)); \
60
+ memmove((char *)abuf + index, buf, sizeof(type)); \
61
+ }
62
+
63
+ #define DefineTypeAccessor(name, type) \
64
+ DefineTypeSetter(name, type); \
65
+ DefineTypeGetter(name, type);
66
+
67
+ #include "array_buffer.h"
68
+ #include "type_array.h"
69
+ #include "data_view.h"
70
+
71
+ #endif
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+
3
+ require 'socket'
4
+
5
+ module TypeArray::IOReader
6
+ def read(io, length)
7
+ buf = nil
8
+ case io
9
+ when BasicSocket
10
+ buf = io.recv(length)
11
+ when IO
12
+ buf = ""
13
+ io.read(length, buf)
14
+ end
15
+ new(buf)
16
+ end
17
+ end
18
+
19
+ module TypeArray::IOWriter
20
+ def write(io)
21
+ case io
22
+ when BasicSocket
23
+ io.send(to_s, 0)
24
+ when IO
25
+ io.write(to_s)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ class TypeArray
2
+ VERSION = '0.1'
3
+ end