123456789_123456789_123456789_123456789_123456789_

Class: FFI::StructLayout::Array

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, Field
Instance Chain:
self, Field
Inherits: FFI::StructLayout::Field
Defined in: ext/ffi_c/StructLayout.c

Overview

An array Field in a ::FFI::StructLayout.

Class Method Summary

Field - Inherited

Instance Method Summary

Constructor Details

This class inherits a constructor from FFI::StructLayout::Field

Instance Method Details

#get(pointer) #an(array)

[ GitHub ]

  
# File 'ext/ffi_c/StructLayout.c', line 357

static VALUE
array_field_get(VALUE self, VALUE pointer)
{
    StructField* f;
    ArrayType* array;
    VALUE argv[2];

    TypedData_Get_Struct(self, StructField, &rbffi_struct_field_data_type, f);
    TypedData_Get_Struct(f->rbType, ArrayType, &rbffi_array_type_data_type, array);

    argv[0] = pointer;
    argv[1] = self;

    return rb_class_new_instance(2, argv, isCharArray(array)
            ? rbffi_StructLayoutCharArrayClass : rbffi_StructInlineArrayClass);
}

#put(pointer, value) #an(array)

[ GitHub ]

  
# File 'ext/ffi_c/StructLayout.c', line 381

static VALUE
array_field_put(VALUE self, VALUE pointer, VALUE value)
{
    StructField* f;
    ArrayType* array;

    TypedData_Get_Struct(self, StructField, &rbffi_struct_field_data_type, f);
    TypedData_Get_Struct(f->rbType, ArrayType, &rbffi_array_type_data_type, array);

    if (isCharArray(array) && rb_obj_is_instance_of(value, rb_cString)) {
        VALUE argv[2];

        argv[0] = INT2FIX(f->offset);
        argv[1] = value;

        if (RSTRING_LEN(value) < array->length) {
            rb_funcall2(pointer, rb_intern("put_string"), 2, argv);
        } else if (RSTRING_LEN(value) == array->length) {
            rb_funcall2(pointer, rb_intern("put_bytes"), 2, argv);
        } else {
            rb_raise(rb_eIndexError, "String is longer (%ld bytes) than the char array (%d bytes)", RSTRING_LEN(value), array->length);
        }
    } else {
#ifdef notyet
        MemoryOp* op;
        int count = RARRAY_LEN(value);
        int i;
        AbstractMemory* memory = MEMORY(pointer);

        if (count > array->length) {
            rb_raise(rb_eIndexError, "array too large");
        }

        /* clear the contents in case of a short write */
        checkWrite(memory);
        checkBounds(memory, f->offset, f->type->ffiType->size);
        if (count < array->length) {
            memset(memory->address + f->offset + (count * array->componentType->ffiType->size),
                    0, (array->length - count) * array->componentType->ffiType->size);
        }

        /* now copy each element in */
        if ((op = get_memory_op(array->componentType)) != NULL) {

            for (i = 0; i < count; ++i) {
                (*op->put)(memory, f->offset + (i * array->componentType->ffiType->size), rb_ary_entry(value, i));
            }

        } else if (array->componentType->nativeType == NATIVE_STRUCT) {

            for (i = 0; i < count; ++i) {
                VALUE entry = rb_ary_entry(value, i);
                Struct* s;

                TypedData_Get_Struct(entry, Struct, &rbffi_struct_data_type, s);

                checkRead(s->pointer);
                checkBounds(s->pointer, 0, array->componentType->ffiType->size);

                memcpy(memory->address + f->offset + (i * array->componentType->ffiType->size),
                        s->pointer->address, array->componentType->ffiType->size);
            }

        } else {
            rb_raise(rb_eNotImpError, "put not supported for arrays of type %s", rb_obj_classname(array->rbComponentType));
        }
#else
        rb_raise(rb_eNotImpError, "cannot set array field");
#endif
    }

    return value;
}