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.
@@ -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