Class: TypeArray

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/type_array/version.rb,
ext/type_array/type_array.c

Defined Under Namespace

Modules: IOReader, IOWriter, Marshal

Constant Summary collapse

VERSION =
'0.3'

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.new(100) ⇒ Int32Array .new("01234567") ⇒ Int32Array .new(buf, 20) ⇒ Int32Array .new(buf, 0, 20) ⇒ Int32Array .new(buf, 20, 20) ⇒ Int32Array

Creates a new TypeArray instance. ArrayBuffer, data (String) and length constructors are supported.

Examples

buf = ArrayBuffer.new(100)         =>  ArrayBuffer

ary = Int32Array.new(buf, 20)      =>  Int32Array
ary.length                         =>  20
ary.byte_length                    =>  80
ary.byte_offset                    =>  20

ary = Int32Array.new(buf, 0, 20)   =>  Int32Array
ary.length                         =>  20
ary.byte_length                    =>  80
ary.byte_offset                    =>  0

ary = Int32Array.new(buf, 20, 20)  =>  Int32Array
ary.length                         =>  20
ary.byte_length                    =>  80
ary.byte_offset                    =>  20

ary = Int32Array.new("01234567")   =>  Int32Array
ary.byte_length                    =>  8
ary.to_s                           =>  "01234567"

ary = Int32Array.new(100)          =>  Int32Array
ary.length                         =>  100
ary.byte_length                    =>  400

Overloads:



353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
# File 'ext/type_array/type_array.c', line 353

static VALUE rb_type_array_s_new(int argc, VALUE *argv, VALUE klass)
{
    VALUE type_array;
    VALUE obj, byte_offset, length;
    rb_type_array_t *array = NULL;
    unsigned long buffer_length, offset;
    if (klass == rb_cTypeArray) rb_raise(rb_eTypeError, "TypeArray cannot be instantiated directly.");
    rb_scan_args(argc, argv, "12", &obj, &byte_offset, &length);
    type_array = Data_Make_Struct(klass, rb_type_array_t, rb_mark_type_array, rb_free_type_array, array);
    array->size = FIX2ULONG(rb_const_get(klass, rb_intern("BYTES_PER_ELEMENT")));
    array->byte_offset = 0;
    array->length = 0;

    if (klass == rb_cInt8Array) {
        array->aref_fn = rb_type_array_aref_int8;
        array->aset_fn = rb_type_array_aset_int8;
        array->mul_fn = rb_type_array_mul_int8;
        array->plus_fn = rb_type_array_plus_int8;
        array->minus_fn = rb_type_array_minus_int8;
        array->div_fn = rb_type_array_div_int8;
        array->eql_fn = rb_type_array_eql_int8;
    } else if (klass == rb_cUInt8Array) {
        array->aref_fn = rb_type_array_aref_uint8;
        array->aset_fn = rb_type_array_aset_uint8;
        array->mul_fn = rb_type_array_mul_uint8;
        array->plus_fn = rb_type_array_plus_uint8;
        array->minus_fn = rb_type_array_minus_uint8;
        array->div_fn = rb_type_array_div_uint8;
        array->eql_fn = rb_type_array_eql_uint8;
    } else if (klass == rb_cInt16Array) {
        array->aref_fn = rb_type_array_aref_int16;
        array->aset_fn = rb_type_array_aset_int16;
        array->mul_fn = rb_type_array_mul_int16;
        array->plus_fn = rb_type_array_plus_int16;
        array->minus_fn = rb_type_array_minus_int16;
        array->div_fn = rb_type_array_div_int16;
        array->eql_fn = rb_type_array_eql_int16;
    } else if (klass == rb_cUInt16Array) {
        array->aref_fn = rb_type_array_aref_uint16;
        array->aset_fn = rb_type_array_aset_uint16;
        array->mul_fn = rb_type_array_mul_uint16;
        array->plus_fn = rb_type_array_plus_uint16;
        array->minus_fn = rb_type_array_minus_uint16;
        array->div_fn = rb_type_array_div_uint16;
        array->eql_fn = rb_type_array_eql_uint16;
    } else if (klass == rb_cInt32Array) {
        array->aref_fn = rb_type_array_aref_int32;
        array->aset_fn = rb_type_array_aset_int32;
        array->mul_fn = rb_type_array_mul_int32;
        array->plus_fn = rb_type_array_plus_int32;
        array->minus_fn = rb_type_array_minus_int32;
        array->div_fn = rb_type_array_div_int32;
        array->eql_fn = rb_type_array_eql_int32;
    } else if (klass == rb_cUInt32Array) {
        array->aref_fn = rb_type_array_aref_uint32;
        array->aset_fn = rb_type_array_aset_uint32;
        array->mul_fn = rb_type_array_mul_uint32;
        array->plus_fn = rb_type_array_plus_uint32;
        array->minus_fn = rb_type_array_minus_uint32;
        array->div_fn = rb_type_array_div_uint32;
        array->eql_fn = rb_type_array_eql_uint32;
    } else if (klass == rb_cFloat32Array) {
        array->aref_fn = rb_type_array_aref_float32;
        array->aset_fn = rb_type_array_aset_float32;
        array->mul_fn = rb_type_array_mul_float32;
        array->plus_fn = rb_type_array_plus_float32;
        array->minus_fn = rb_type_array_minus_float32;
        array->div_fn = rb_type_array_div_float32;
        array->eql_fn = rb_type_array_eql_float32;
    } else if (klass == rb_cFloat64Array) {
        array->aref_fn = rb_type_array_aref_float64;
        array->aset_fn = rb_type_array_aset_float64;
        array->mul_fn = rb_type_array_mul_float64;
        array->plus_fn = rb_type_array_plus_float64;
        array->minus_fn = rb_type_array_minus_float64;
        array->div_fn = rb_type_array_div_float64;
        array->eql_fn = rb_type_array_eql_float64;
    }

    if (FIXNUM_P(obj)) {
        array->length = FIX2ULONG(obj);
        array->byte_length = (array->length * array->size);
        array->buf = rb_alloc_array_buffer(array->byte_length, NULL);
    } else if (rb_type(obj) == T_STRING) {
        array->byte_length = (unsigned long)RSTRING_LEN(obj);
        array->length = (array->byte_length / array->size);
        ArrayBufferEncode(obj);
        array->buf = rb_alloc_array_buffer(array->byte_length, (void *)RSTRING_PTR(obj));
    } else if (rb_class_of(obj) == rb_cArrayBuffer) {
        GetArrayBuffer(obj);
        if (!NIL_P(byte_offset)) {
            Check_Type(byte_offset, T_FIXNUM);
            array->byte_offset = FIX2ULONG(byte_offset);
            if (!rb_type_array_assert_alignment(array->byte_offset, array->size))
                rb_raise(rb_eRangeError, "Byte offset is not aligned.");
        }
        buffer_length = buf->length;
        if (!NIL_P(length)) {
            Check_Type(length, T_FIXNUM);
            array->length = FIX2ULONG(length);
            array->byte_length = array->length * array->size;
        } else {
            array->byte_length = buffer_length - array->byte_offset;
        }
        if ((array->byte_offset + array->byte_length) > buffer_length)
            rb_raise(rb_eRangeError, "Byte offset / length is not aligned.");
        if (array->length == 0) array->length = array->byte_length / array->size;
        if (array->byte_offset > buffer_length || array->byte_offset + array->length > buffer_length ||
             array->byte_offset + array->length * array->size > buffer_length) {
             rb_raise(rb_eRangeError, "Length is out of range.");
        }
        array->buf = obj;
    } else if (rb_obj_is_kind_of(obj, rb_cTypeArray) == Qtrue) {
        GetTypeArray(obj);
        array->length = ary->length;
        array->byte_length = (array->size * array->length);
        array->buf = rb_alloc_array_buffer(array->byte_length, NULL);
        array->byte_offset = 0;
        for (offset = 0; offset < array->length; ++offset) {
          VALUE offs = INT2FIX(offset);
          VALUE val = rb_funcall(obj, rb_type_array_intern_aget, 1, offs);
          rb_funcall(type_array, rb_type_array_intern_aset, 2, offs, val);
        }
    } else {
        rb_raise(rb_eTypeError, "TypeArray constructor %s not supported.", RSTRING_PTR(rb_obj_as_string(obj)));
    }
    rb_obj_call_init(type_array, 0, NULL);
    return type_array;
}

Instance Method Details

#[](1) ⇒ Fixnum, ...

Gets a value at a given offset, with coercion dependent on the array type of this instance.

Examples

ary = Int32Array.new("01234567")  =>  Int32Array
ary[1] = 23                       =>  nil
ary[1]                            =>  23

Returns:

  • (Fixnum, Bignum, Float)


750
751
752
753
754
755
756
# File 'ext/type_array/type_array.c', line 750

static VALUE rb_type_array_aget(VALUE obj, VALUE idx)
{
    GetTypeArray(obj);
    GetArrayBuffer(ary->buf);
    long index = rb_type_array_assert_offset(ary, idx);
    return ary->aref_fn(buf->buf, index);
}

#[]=(1) ⇒ nil

Sets a value at a given offset, with coercion dependent on the array type of this instance.

Examples

ary = Int32Array.new("01234567")  =>  Int32Array
ary[1] = 23                       =>  nil

Returns:

  • (nil)


721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
# File 'ext/type_array/type_array.c', line 721

static VALUE rb_type_array_aset(VALUE obj, VALUE idx, VALUE item)
{
    GetTypeArray(obj);
    GetArrayBuffer(ary->buf);
    long index = rb_type_array_assert_offset(ary, idx);
    switch (TYPE(item)) {
    case T_FIXNUM:
    case T_BIGNUM:
    case T_FLOAT:
        break;
    default:
        rb_raise(rb_eTypeError, "Type arrays only support Fixnum, Bignum and Float instances");
    }
    ary->aset_fn(buf->buf, index, item);
    return Qnil;
}

#bufferString

Returns the underlying buffer managed by this ArrayBuffer instance.

Examples

ary = Int32Array.new("buffer")  =>  DataView
ary.buffer                      =>  ArrayBuffer

Returns:

  • (String)


666
667
668
669
670
# File 'ext/type_array/type_array.c', line 666

static VALUE rb_type_array_buffer(VALUE obj)
{
    GetTypeArray(obj);
    return ary->buf; 
}

#byte_lengthFixnum

Returns the size of the underlying buffer managed by this TypeArray instance.

Examples

ary = Int32Array.new("01234567")  =>  Int32Array
ary.byte_length                   =>  8

Returns:

  • (Fixnum)


494
495
496
497
498
# File 'ext/type_array/type_array.c', line 494

static VALUE rb_type_array_byte_length(VALUE obj)
{
    GetTypeArray(obj);
    return ULONG2NUM(ary->byte_length);
}

#byte_offsetFixnum

Returns the offset into the underlying buffer managed by this TypeArray instance.

Examples

ary = Int32Array.new("01234567")     =>  Int32Array
ary.byte_offset                      =>  0

ary = Int32Array.new("01234567", 2)  =>  Int32Array
ary.byte_offset                      =>  2

Returns:

  • (Fixnum)


704
705
706
707
708
# File 'ext/type_array/type_array.c', line 704

static VALUE rb_type_array_byte_offset(VALUE obj)
{
    GetTypeArray(obj);
    return ULONG2NUM(ary->byte_offset);
}

#div(0, 1) ⇒ Fixnum, ...

Gets two values at given offsets and divides them - only the result’s coerced to a Ruby object.

Examples

buf = ArrayBuffer.new(16)         =>  ArrayBuffer
ary = Int32Array.new(buf)         =>  Int32Array
ary[0] = 2                        =>  nil
ary[1] = 4                        =>  nil
ary[2] = 8                        =>  nil

ary.div(1, 0)                     =>  2
ary.div(2, 1)                     =>  2

Returns:

  • (Fixnum, Bignum, Float)


600
601
602
603
604
605
606
607
608
609
610
# File 'ext/type_array/type_array.c', line 600

static VALUE rb_type_array_div(int argc, VALUE *argv, VALUE obj)
{
    VALUE off1, off2, off3;
    GetTypeArray(obj);
    GetArrayBuffer(ary->buf);
    rb_scan_args(argc, argv, "21", &off1, &off2, &off3);
    long offset1 = rb_type_array_assert_offset(ary, off1);
    long offset2 = rb_type_array_assert_offset(ary, off2);
    long offset3 = NIL_P(off3) ? 0 : rb_type_array_assert_offset(ary, off3);
    return ary->div_fn(buf->buf, offset1, offset2, offset3);
}

#each {|item| ... } ⇒ TypeArray

Calls block once for each element in self, passing that element as a parameter.

Examples

buf = ArrayBuffer.new(16)         =>  ArrayBuffer

ary = Int32Array.new(buf)         =>  Int32Array
ary[0] = 2                        =>  nil
ary[1] = 4                        =>  nil
ary[2] = 8                        =>  nil
ary[3] = 16                       =>  nil

ary.map(&:to_s)                   =>  %w(2 4 8 16)

Yields:

  • (item)

Returns:



776
777
778
779
780
781
782
783
784
785
786
787
# File 'ext/type_array/type_array.c', line 776

static VALUE rb_type_array_each(VALUE obj)
{
    long index;
    GetTypeArray(obj);
    GetArrayBuffer(ary->buf);

    RETURN_ENUMERATOR(obj, 0, 0);
    for (index = 0; index < ary->length; index++) {
        rb_yield(ary->aref_fn(buf->buf, (index * ary->size)));
    }
    return obj;
}

#eql(0, 1) ⇒ true

Gets two values at given offsets and compares them - a boolean’s returned

Examples

buf = ArrayBuffer.new(16)         =>  ArrayBuffer
ary = Int32Array.new(buf)         =>  Int32Array
ary[0] = 2                        =>  nil
ary[1] = 4                        =>  nil
ary[2] = 8                        =>  nil

ary.eql(1, 0)                     =>  false
ary.eql(2, 2)                     =>  true

Returns:

  • (true)


628
629
630
631
632
633
634
635
# File 'ext/type_array/type_array.c', line 628

static VALUE rb_type_array_eql(VALUE obj, VALUE off1, VALUE off2)
{
    GetTypeArray(obj);
    GetArrayBuffer(ary->buf);
    long offset1 = rb_type_array_assert_offset(ary, off1);
    long offset2 = rb_type_array_assert_offset(ary, off2);
    return ary->eql_fn(buf->buf, offset1, offset2, 0);
}

#lengthFixnum

Returns the max number of elements this typed array instance can accommodate.

Examples

ary = Int32Array.new("01234567")  =>  Int32Array
ary.byte_length                   =>  8
ary.length                        =>  2

Returns:

  • (Fixnum)


649
650
651
652
653
# File 'ext/type_array/type_array.c', line 649

static VALUE rb_type_array_length(VALUE obj)
{
    GetTypeArray(obj);
    return ULONG2NUM(ary->length);
}

#minus(0, 1) ⇒ Fixnum, ...

Gets two values at given offsets and subtracts them - only the result’s coerced to a Ruby object.

Examples

buf = ArrayBuffer.new(16)         =>  ArrayBuffer
ary = Int32Array.new(buf)         =>  Int32Array
ary[0] = 2                        =>  nil
ary[1] = 4                        =>  nil
ary[2] = 8                        =>  nil

ary.minus(1, 0)                   =>  2
ary.minus(2, 1)                   =>  4

Returns:

  • (Fixnum, Bignum, Float)


572
573
574
575
576
577
578
579
580
581
582
# File 'ext/type_array/type_array.c', line 572

static VALUE rb_type_array_minus(int argc, VALUE *argv, VALUE obj)
{
    VALUE off1, off2, off3;
    GetTypeArray(obj);
    GetArrayBuffer(ary->buf);
    rb_scan_args(argc, argv, "21", &off1, &off2, &off3);
    long offset1 = rb_type_array_assert_offset(ary, off1);
    long offset2 = rb_type_array_assert_offset(ary, off2);
    long offset3 = NIL_P(off3) ? 0 : rb_type_array_assert_offset(ary, off3);
    return ary->minus_fn(buf->buf, offset1, offset2, offset3);
}

#mul(0, 1) ⇒ Fixnum, ...

Gets two values at given offsets and multiples them - only the result’s coerced to a Ruby object.

Examples

buf = ArrayBuffer.new(16)         =>  ArrayBuffer
ary = Int32Array.new(buf)         =>  Int32Array
ary[0] = 2                        =>  nil
ary[1] = 4                        =>  nil
ary[2] = 8                        =>  nil

ary.mul(0,1)                      =>  8
ary.mul(1,2)                      =>  32

Returns:

  • (Fixnum, Bignum, Float)


516
517
518
519
520
521
522
523
524
525
526
# File 'ext/type_array/type_array.c', line 516

static VALUE rb_type_array_mul(int argc, VALUE *argv, VALUE obj)
{
    VALUE off1, off2, off3;
    GetTypeArray(obj);
    GetArrayBuffer(ary->buf);
    rb_scan_args(argc, argv, "21", &off1, &off2, &off3);
    long offset1 = rb_type_array_assert_offset(ary, off1);
    long offset2 = rb_type_array_assert_offset(ary, off2);
    long offset3 = NIL_P(off3) ? 0 : rb_type_array_assert_offset(ary, off3);
    return ary->mul_fn(buf->buf, offset1, offset2, offset3);
}

#plus(0, 1) ⇒ Fixnum, ...

Gets two values at given offsets and adds them - only the result’s coerced to a Ruby object.

Examples

buf = ArrayBuffer.new(16)         =>  ArrayBuffer
ary = Int32Array.new(buf)         =>  Int32Array
ary[0] = 2                        =>  nil
ary[1] = 4                        =>  nil
ary[2] = 8                        =>  nil

ary.plus(0,1)                     =>  6
ary.plus(1,2)                     =>  12

Returns:

  • (Fixnum, Bignum, Float)


544
545
546
547
548
549
550
551
552
553
554
# File 'ext/type_array/type_array.c', line 544

static VALUE rb_type_array_plus(int argc, VALUE *argv, VALUE obj)
{
    VALUE off1, off2, off3;
    GetTypeArray(obj);
    GetArrayBuffer(ary->buf);
    rb_scan_args(argc, argv, "21", &off1, &off2, &off3);
    long offset1 = rb_type_array_assert_offset(ary, off1);
    long offset2 = rb_type_array_assert_offset(ary, off2);
    long offset3 = NIL_P(off3) ? 0 : rb_type_array_assert_offset(ary, off3);
    return ary->plus_fn(buf->buf, offset1, offset2, offset3);
}

#to_sString

Returns a String (binary) representation of the underlying buffer managed by this TypeArray instance.

Examples

buf = ArrayBuffer.new("buffer")  =>  ArrayBuffer
ary = Int32Array.new(buf)        =>  Int32Array
ary.to_s                         =>  "buffer"

Returns:

  • (String)


684
685
686
687
688
# File 'ext/type_array/type_array.c', line 684

static VALUE rb_type_array_to_s(VALUE obj)
{
    GetTypeArray(obj);
    return rb_array_buffer_to_s(ary->buf); 
}