Class: FFI::AbstractMemory

Inherits:
Object
  • Object
show all
Defined in:
ext/ffi_c/AbstractMemory.c,
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

Instance Method Summary collapse

Instance Method Details

#[](idx) ⇒ Object

Memory read accessor.

Parameters:

  • idx (Numeric)

    index to access in memory

Returns:



653
654
655
656
657
658
659
660
661
662
663
664
# File 'ext/ffi_c/AbstractMemory.c', line 653

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

    Data_Get_Struct(self, AbstractMemory, ptr);

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

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

#__copy_from__(rbsrc, rblen) ⇒ Object



672
673
674
675
676
677
678
679
680
681
682
# File 'ext/ffi_c/AbstractMemory.c', line 672

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

    Data_Get_Struct(self, AbstractMemory, dst);

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

    return self;
}

#clearself

Set the memory to all-zero.

Returns:

  • (self)


307
308
309
310
311
312
313
# File 'ext/ffi_c/AbstractMemory.c', line 307

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

#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



338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
# File 'ext/ffi_c/AbstractMemory.c', line 338

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

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

    Data_Get_Struct(self, AbstractMemory, ptr);
    Data_Get_Struct(nType, Type, type);

    MemoryOp *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



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

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);

    Data_Get_Struct(self, AbstractMemory, 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_tainted_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_tainted_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



533
534
535
536
537
538
539
540
541
542
543
544
545
546
# File 'ext/ffi_c/AbstractMemory.c', line 533

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_tainted_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



405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
# File 'ext/ffi_c/AbstractMemory.c', line 405

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_tainted_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



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

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

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

    Data_Get_Struct(self, AbstractMemory, ptr);
    Data_Get_Struct(nType, Type, type);

    MemoryOp *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



561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
# File 'ext/ffi_c/AbstractMemory.c', line 561

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);

    if (rb_safe_level() >= 1 && OBJ_TAINTED(str)) {
        rb_raise(rb_eSecurityError, "Writing unsafe string to memory");
        return Qnil;
    }
    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



505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
# File 'ext/ffi_c/AbstractMemory.c', line 505

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)


602
603
604
605
606
# File 'ext/ffi_c/AbstractMemory.c', line 602

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:

#sizeNumeric Also known as: size

Return memory size in bytes (alias: #total)

Returns:

  • (Numeric)


320
321
322
323
324
325
326
327
328
# File 'ext/ffi_c/AbstractMemory.c', line 320

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

    Data_Get_Struct(self, AbstractMemory, ptr);

    return LONG2NUM(ptr->size);
}

#type_sizeNumeric

Get the memory's type size.

Returns:

  • (Numeric)

    type size in bytes



636
637
638
639
640
641
642
643
644
# File 'ext/ffi_c/AbstractMemory.c', line 636

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

    Data_Get_Struct(self, AbstractMemory, 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)


617
618
619
620
621
622
623
624
625
626
627
628
629
# File 'ext/ffi_c/AbstractMemory.c', line 617

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)