Class: FFI::AbstractMemory

Inherits:
Object
  • Object
show all
Defined in:
ext/ffi_c/AbstractMemory.c,
lib/ffi/abstract_memory.rb,
ext/ffi_c/AbstractMemory.c

Overview

AbstractMemory is the base class for many memory management classes such as Buffer.

This class has a lot of methods to work with integers :

  • put_intsize(offset, value)

  • get_intsize(offset)

  • put_uintsize(offset, value)

  • get_uintsize(offset)

  • writeuintsize(value)

  • read_intsize

  • write_uintsize(value)

  • read_uintsize

  • put_array_of_intsize(offset, ary)

  • get_array_of_intsize(offset, length)

  • put_array_of_uintsize(offset, ary)

  • get_array_of_uintsize(offset, length)

  • write_array_of_intsize(ary)

  • read_array_of_intsize(length)

  • write_array_of_uintsize(ary)

  • read_array_of_uintsize(length)

where size is 8, 16, 32 or 64. Same methods exist for long type.

Aliases exist : char for int8, short for int16, int for int32 and long_long for int64.

Others methods are listed below.

Direct Known Subclasses

Buffer, Pointer

Constant Summary collapse

LONG_MAX =
FFI::Pointer.new(1).size

Instance Method Summary collapse

Instance Method Details

#[](idx) ⇒ Object

Memory read accessor.

Parameters:

  • idx (Numeric)

    index to access in memory

Returns:



660
661
662
663
664
665
666
667
668
669
670
671
# File 'ext/ffi_c/AbstractMemory.c', line 660

static VALUE
memory_aref(VALUE self, VALUE idx)
{
    AbstractMemory* ptr;
    VALUE rbOffset = Qnil;

    TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr);

    rbOffset = ULONG2NUM(NUM2ULONG(idx) * ptr->typeSize);

    return rb_funcall2(self, id_plus, 1, &rbOffset);
}

#__copy_from__(rbsrc, rblen) ⇒ Object



681
682
683
684
685
686
687
688
689
690
691
# File 'ext/ffi_c/AbstractMemory.c', line 681

static VALUE
memory_copy_from(VALUE self, VALUE rbsrc, VALUE rblen)
{
    AbstractMemory* dst;

    TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, dst);

    memcpy(dst->address, rbffi_AbstractMemory_Cast(rbsrc, &rbffi_abstract_memory_data_type)->address, NUM2INT(rblen));

    return self;
}

#clearself

Set the memory to all-zero.

Returns:

  • (self)


315
316
317
318
319
320
321
322
# File 'ext/ffi_c/AbstractMemory.c', line 315

static VALUE
memory_clear(VALUE self)
{
    AbstractMemory* ptr = MEMORY(self);
    checkWrite(ptr);
    memset(ptr->address, 0, ptr->size);
    return self;
}

#freezeObject

Freeze the AbstractMemory object and unset the writable flag.



699
700
701
702
703
704
705
# File 'ext/ffi_c/AbstractMemory.c', line 699

static VALUE
memory_freeze(VALUE self)
{
    AbstractMemory* ptr = MEMORY(self);
    ptr->flags &= ~MEM_WR;
    return rb_call_super(0, NULL);
}

#get(type, offset) ⇒ Object

Return data of given type contained in memory.

Parameters:

  • type_name (Symbol, Type)

    type of data to get

  • offset (Numeric)

    point in buffer to start from

Returns:

  • (Object)

Raises:

  • (ArgumentError)

    if type is not supported



347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
# File 'ext/ffi_c/AbstractMemory.c', line 347

static VALUE
memory_get(VALUE self, VALUE type_name, VALUE offset)
{
    AbstractMemory* ptr;
    VALUE nType;
    Type *type;
    MemoryOp *op;

    nType = rbffi_Type_Lookup(type_name);
    if(NIL_P(nType)) goto undefined_type;

    TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr);
    TypedData_Get_Struct(nType, Type, &rbffi_type_data_type, type);

    op = get_memory_op(type);
    if(op == NULL) goto undefined_type;

    return op->get(ptr, NUM2LONG(offset));

undefined_type: {
    VALUE msg = rb_sprintf("undefined type '%" PRIsVALUE "'", type_name);
    rb_exc_raise(rb_exc_new3(rb_eArgError, msg));
    return Qnil;
  }
}

#get_array_of_float32(offset, length) ⇒ Array<Float> Also known as: get_array_of_float

Get 32-bit floats in memory from offset offset (alias: #get_array_of_float).

Parameters:

  • offset (Numeric)
  • length (Numeric)

    number of Float to get

Returns:

  • (Array<Float>)

#get_array_of_float64(offset, length) ⇒ Array<Float> Also known as: get_array_of_double

Get 64-bit floats (doubles) in memory from offset offset (alias: #get_array_of_double).

Parameters:

  • offset (Numeric)
  • length (Numeric)

    number of Float to get

Returns:

  • (Array<Float>)

#get_array_of_pointer(offset, length) ⇒ Array<Pointer>

Get an array of Pointer of length length from offset.

Parameters:

  • offset (Numeric)
  • length (Numeric)

Returns:

#get_array_of_string(offset, count = nil) ⇒ Array<String>

Return an array of strings contained in memory.

Parameters:

  • offset (Numeric)

    point in memory to start from

  • count (Numeric)

    number of strings to get. If nil, return all strings

Returns:

  • (Array<String>)

Raises:

  • (IndexError)

    if offset is too great

  • (NullPointerError)

    if memory not initialized



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
482
# File 'ext/ffi_c/AbstractMemory.c', line 444

static VALUE
memory_get_array_of_string(int argc, VALUE* argv, VALUE self)
{
    VALUE offset = Qnil, countnum = Qnil, retVal = Qnil;
    AbstractMemory* ptr;
    long off;
    int count;

    rb_scan_args(argc, argv, "11", &offset, &countnum);
    off = NUM2LONG(offset);
    count = (countnum == Qnil ? 0 : NUM2INT(countnum));
    retVal = rb_ary_new2(count);

    TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr);
    checkRead(ptr);

    if (countnum != Qnil) {
        int i;

        checkBounds(ptr, off, count * sizeof (char*));

        for (i = 0; i < count; ++i) {
            const char* strptr = *((const char**) (ptr->address + off) + i);
            rb_ary_push(retVal, (strptr == NULL ? Qnil : rb_str_new2(strptr)));
        }

    } else {
        checkBounds(ptr, off, sizeof (char*));
        for ( ; off < ptr->size - (long) sizeof (void *); off += (long) sizeof (void *)) {
            const char* strptr = *(const char**) (ptr->address + off);
            if (strptr == NULL) {
                break;
            }
            rb_ary_push(retVal, rb_str_new2(strptr));
        }
    }

    return retVal;
}

#get_bytes(offset, length) ⇒ String

Return string contained in memory.

Parameters:

  • offset (Numeric)

    point in buffer to start from

  • length (Numeric)

    string’s length in bytes.

Returns:

  • (String)

Raises:

  • (IndexError)

    if length is too great

  • (NullPointerError)

    if memory not initialized



544
545
546
547
548
549
550
551
552
553
554
555
556
557
# File 'ext/ffi_c/AbstractMemory.c', line 544

static VALUE
memory_get_bytes(VALUE self, VALUE offset, VALUE length)
{
    AbstractMemory* ptr = MEMORY(self);
    long off, len;

    off = NUM2LONG(offset);
    len = NUM2LONG(length);

    checkRead(ptr);
    checkBounds(ptr, off, len);

    return rb_str_new((char *) ptr->address + off, len);
}

#get_float32(offset) ⇒ Float Also known as: get_float

Get a 32-bit float from memory at offset offset (alias: #get_float).

Parameters:

  • offset (Numeric)

Returns:

  • (Float)

#get_float64(offset) ⇒ Float Also known as: get_double

Get a 64-bit float (double) from memory at offset offset (alias: #get_double).

Parameters:

  • offset (Numeric)

Returns:

  • (Float)

#get_pointer(offset) ⇒ Pointer

Get a Pointer to the memory from offset.

Parameters:

  • offset (Numeric)

Returns:

#get_string(offset, length = nil) ⇒ String

Return string contained in memory.

Parameters:

  • offset (Numeric)

    point in buffer to start from

  • length (Numeric)

    string’s length in bytes. If nil, a (memory size - offset) length string is returned).

Returns:

  • (String)

Raises:

  • (IndexError)

    if length is too great

  • (NullPointerError)

    if memory not initialized



416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
# File 'ext/ffi_c/AbstractMemory.c', line 416

static VALUE
memory_get_string(int argc, VALUE* argv, VALUE self)
{
    VALUE length = Qnil, offset = Qnil;
    AbstractMemory* ptr = MEMORY(self);
    long off, len;
    char* end;
    int nargs = rb_scan_args(argc, argv, "11", &offset, &length);

    off = NUM2LONG(offset);
    len = nargs > 1 && length != Qnil ? NUM2LONG(length) : (ptr->size - off);
    checkRead(ptr);
    checkBounds(ptr, off, len);

    end = memchr(ptr->address + off, 0, len);
    return rb_str_new((char *) ptr->address + off,
            (end != NULL ? end - ptr->address - off : len));
}

#put(type, offset, value) ⇒ nil

Parameters:

  • type_name (Symbol, Type)

    type of data to put

  • offset (Numeric)

    point in buffer to start from

Returns:

  • (nil)

Raises:

  • (ArgumentError)

    if type is not supported



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
# File 'ext/ffi_c/AbstractMemory.c', line 380

static VALUE
memory_put(VALUE self, VALUE type_name, VALUE offset, VALUE value)
{
    AbstractMemory* ptr;
    VALUE nType;
    Type *type;
    MemoryOp *op;

    nType = rbffi_Type_Lookup(type_name);
    if(NIL_P(nType)) goto undefined_type;

    TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr);
    TypedData_Get_Struct(nType, Type, &rbffi_type_data_type, type);

    op = get_memory_op(type);
    if(op == NULL) goto undefined_type;

    op->put(ptr, NUM2LONG(offset), value);
    return Qnil;

undefined_type: {
    VALUE msg = rb_sprintf("unsupported type '%" PRIsVALUE "'", type_name);
    rb_exc_raise(rb_exc_new3(rb_eArgError, msg));
    return Qnil;
  }
}

#put_array_of_float32(offset, ary) ⇒ self Also known as: put_array_of_float

Put values from ary as 32-bit floats in memory from offset offset (alias: #put_array_of_float).

Parameters:

  • offset (Numeric)
  • ary (Array<Numeric>)

Returns:

  • (self)

#put_array_of_float64(offset, ary) ⇒ self Also known as: put_array_of_double

Put values from ary as 64-bit floats (doubles) in memory from offset offset (alias: #put_array_of_double).

Parameters:

  • offset (Numeric)
  • ary (Array<Numeric>)

Returns:

  • (self)

#put_array_of_pointer(offset, ary) ⇒ self

Put an array of Pointer into memory from offset.

Parameters:

  • offset (Numeric)
  • ary (Array<#to_ptr>)

Returns:

  • (self)

#put_bytes(offset, str, index = 0, length = nil) ⇒ self

Put a string in memory.

Parameters:

  • offset (Numeric)

    point in buffer to start from

  • str (String)

    string to put to memory

  • index (Numeric)
  • length (Numeric)

    string’s length in bytes. If nil, a (memory size - offset) length string is returned).

Returns:

  • (self)

Raises:

  • (IndexError)

    if length is too great

  • (NullPointerError)

    if memory not initialized

  • (RangeError)

    if index is negative, or if index+length is greater than size of string

  • (SecurityError)

    when writing unsafe string to memory



572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
# File 'ext/ffi_c/AbstractMemory.c', line 572

static VALUE
memory_put_bytes(int argc, VALUE* argv, VALUE self)
{
    AbstractMemory* ptr = MEMORY(self);
    VALUE offset = Qnil, str = Qnil, rbIndex = Qnil, rbLength = Qnil;
    long off, len, idx;
    int nargs = rb_scan_args(argc, argv, "22", &offset, &str, &rbIndex, &rbLength);

    Check_Type(str, T_STRING);

    off = NUM2LONG(offset);
    idx = nargs > 2 ? NUM2LONG(rbIndex) : 0;
    if (idx < 0) {
        rb_raise(rb_eRangeError, "index cannot be less than zero");
        return Qnil;
    }
    len = nargs > 3 ? NUM2LONG(rbLength) : (RSTRING_LEN(str) - idx);
    if ((idx + len) > RSTRING_LEN(str)) {
        rb_raise(rb_eRangeError, "index+length is greater than size of string");
        return Qnil;
    }

    checkWrite(ptr);
    checkBounds(ptr, off, len);

    memcpy(ptr->address + off, RSTRING_PTR(str) + idx, len);

    return self;
}

#put_float32offsetself Also known as: put_float

Put value as a 32-bit float in memory at offset offset (alias: #put_float).

Parameters:

  • offset (Numeric)
  • value (Numeric)

Returns:

  • (self)

#put_float64(offset, value) ⇒ self Also known as: put_double

Put value as a 64-bit float (double) in memory at offset offset (alias: #put_double).

Parameters:

  • offset (Numeric)
  • value (Numeric)

Returns:

  • (self)

#put_pointer(offset, value) ⇒ self

Put value in memory from offset..

Parameters:

  • offset (Numeric)
  • value (nil, Pointer, Integer, #to_ptr)

Returns:

  • (self)

#put_string(offset, str) ⇒ self

Put a string in memory.

Parameters:

  • offset (Numeric)
  • str (String)

Returns:

  • (self)

Raises:

  • (SecurityError)

    when writing unsafe string to memory

  • (IndexError)

    if offset is too great

  • (NullPointerError)

    if memory not initialized



516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
# File 'ext/ffi_c/AbstractMemory.c', line 516

static VALUE
memory_put_string(VALUE self, VALUE offset, VALUE str)
{
    AbstractMemory* ptr = MEMORY(self);
    long off, len;

    Check_Type(str, T_STRING);
    off = NUM2LONG(offset);
    len = RSTRING_LEN(str);

    checkWrite(ptr);
    checkBounds(ptr, off, len + 1);

    memcpy(ptr->address + off, RSTRING_PTR(str), len);
    *((char *) ptr->address + off + len) = '\0';

    return self;
}

#read_array_of_double(length) ⇒ Array<Float>

Read 64-bit floats (doubles) from memory.

Same as:

memory.get_array_of_double(0, ary)

Parameters:

  • length (Numeric)

    number of Float to read

Returns:

  • (Array<Float>)

#read_array_of_float(length) ⇒ Array<Float>

Read 32-bit floats from memory.

Same as:

memory.get_array_of_float(0, ary)

Parameters:

  • length (Numeric)

    number of Float to read

Returns:

  • (Array<Float>)

#read_array_of_pointer(length) ⇒ Array<Pointer>

Read an array of Pointer of length length.

Same as:

memory.get_array_of_pointer(0, length)

Parameters:

  • length (Numeric)

Returns:

#read_bytes(length) ⇒ String

equivalent to :

memory.get_bytes(0, length)

Parameters:

  • length (Numeric)

    of string to return

Returns:

  • (String)


609
610
611
612
613
# File 'ext/ffi_c/AbstractMemory.c', line 609

static VALUE
memory_read_bytes(VALUE self, VALUE length)
{
    return memory_get_bytes(self, INT2FIX(0), length);
}

#read_doubleFloat

Read a 64-bit float (double) from memory.

Same as:

memory.get_double(0)

Returns:

  • (Float)

#read_floatFloat

Read a 32-bit float from memory.

Same as:

memory.get_float(0)

Returns:

  • (Float)

#read_pointerPointer

Get a Pointer to the memory from base address.

Equivalent to:

memory.get_pointer(0)

Returns:

#size_limit?Boolean

Return true if self has a size limit.

Returns:

  • (Boolean)


40
41
42
# File 'lib/ffi/abstract_memory.rb', line 40

def size_limit?
  size != LONG_MAX
end

#sizeNumeric Also known as: size

Return memory size in bytes (alias: #total)

Returns:

  • (Numeric)


329
330
331
332
333
334
335
336
337
# File 'ext/ffi_c/AbstractMemory.c', line 329

static VALUE
memory_size(VALUE self)
{
    AbstractMemory* ptr;

    TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr);

    return LONG2NUM(ptr->size);
}

#type_sizeNumeric

Get the memory’s type size.

Returns:

  • (Numeric)

    type size in bytes



643
644
645
646
647
648
649
650
651
# File 'ext/ffi_c/AbstractMemory.c', line 643

static VALUE
memory_type_size(VALUE self)
{
    AbstractMemory* ptr;

    TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr);

    return INT2NUM(ptr->typeSize);
}

#write_array_of_double(ary) ⇒ self

Write values from ary as 64-bit floats (doubles) in memory.

Same as:

memory.put_array_of_double(0, ary)

Parameters:

  • ary (Array<Numeric>)

Returns:

  • (self)

#write_array_of_float(ary) ⇒ self

Write values from ary as 32-bit floats in memory.

Same as:

memory.put_array_of_float(0, ary)

Parameters:

  • ary (Array<Numeric>)

Returns:

  • (self)

#write_array_of_pointer(ary) ⇒ self

Write an array of Pointer into memory from offset.

Same as :

memory.put_array_of_pointer(0, ary)

Parameters:

  • ary (Array<#to_ptr>)

Returns:

  • (self)

#write_bytes(str, index = 0, length = nil) ⇒ self

equivalent to :

memory.put_bytes(0, str, index, length)

Parameters:

  • str (String)

    string to put to memory

  • index (Numeric)
  • length (Numeric)

    string’s length in bytes. If nil, a (memory size - offset) length string is returned).

Returns:

  • (self)


624
625
626
627
628
629
630
631
632
633
634
635
636
# File 'ext/ffi_c/AbstractMemory.c', line 624

static VALUE
memory_write_bytes(int argc, VALUE* argv, VALUE self)
{
    VALUE* wargv = ALLOCA_N(VALUE, argc + 1);
    int i;

    wargv[0] = INT2FIX(0);
    for (i = 0; i < argc; i++) {
        wargv[i + 1] = argv[i];
    }

    return memory_put_bytes(argc + 1, wargv, self);
}

#write_double(value) ⇒ self

Write value as a 64-bit float (double) in memory.

Same as:

memory.put_double(0, value)

Parameters:

  • value (Numeric)

Returns:

  • (self)

#write_float(value) ⇒ self

Write value as a 32-bit float in memory.

Same as:

memory.put_float(0, value)

Parameters:

  • value (Numeric)

Returns:

  • (self)

#write_pointer(value) ⇒ self

Write value in memory.

Equivalent to:

memory.put_pointer(0, value)

Parameters:

  • value (nil, Pointer, Integer, #to_ptr)

Returns:

  • (self)