Class: Snow::Memory
- Inherits:
-
Object
- Object
- Snow::Memory
- Defined in:
- lib/snow-data/memory.rb,
ext/snow-data/snow-data.c
Overview
A class for representing blocks of memory. You can either allocate memory using ::malloc or wrap existing blocks of memory using ::new or ::wrap (or ::__wrap__ if a subclass has extended ::wrap and ::new).
If wrapping an existing block of memory, note that the Memory object does not take ownership of the block. As such, freeing it is the responsibility of its allocator. Only a block allocated by ::malloc will be freed by a Memory object, either by calling #free! or when the GC collects the object.
When subclassing Memory, which is fine to do, you’ll likely want to override Memory::new and possibly Memory::wrap. It is also possible to override Memory::malloc, but it’s recommended you never do this. If you do, keep in mind that __malloc__ exists as an alias of malloc and you must never try to override it, as this could result in very strange behavior. Similarly, new is aliased as both wrap and __wrap__, the latter of which you should must never override either. Again, it may result in undesirable behavior, crashes, and angry responses to any issues you create on GitHub as a result.
Constant Summary collapse
- HAS_ALLOCA =
Whether or not __alloca__ is available (and ergo any other variant of it). You may check this instead of calling respond_to? if you wish.
self.respond_to?(:__alloca__)
Class Method Summary collapse
-
.__alloca__(sd_size) ⇒ Object
Allocates size bytes on the stack and yields it to a block before for use, then returns the result of the block.
-
.__malloc__(*args) ⇒ Object
(also: malloc, [])
Allocates a new block with the given size and alignment and returns it.
-
.__wrap__(*args) ⇒ Object
(also: new, wrap)
Creates a new Memory object that wraps an existing pointer.
-
.align_size(size_or_offset, alignment = nil) ⇒ Integer
Aligns a given size or offset to a specific alignment.
Instance Method Summary collapse
-
#==(other) ⇒ Object
Returns whether this and another block are equal in terms of their properties – that is, whether they have the address and bytesize.
-
#address ⇒ Integer
Gets the address of this memory block as an Integer.
-
#alignment ⇒ Object
The alignment in bytes of a memory block.
-
#bytesize ⇒ Object
The size in bytes of a memory block.
-
#copy!(source, destination_offset = nil, source_offset = nil, byte_size = nil) ⇒ self
Copies byte_size bytes from an offset in the source data to an offset into the receiver (the destination).
-
#dup ⇒ Object
Creates a new block of memory with the same class, size, and alignment; copies the receiver’s data to the new block; and returns the new block.
-
#free! ⇒ self
Frees any memory owned by the object.
-
#get_char(offset) ⇒ String
Reads a char from the offset into the memory block and returns it.
-
#get_double(offset) ⇒ Object
Reads a double from the offset into the memory block and returns it.
-
#get_float(offset) ⇒ Float
Reads a float from the offset into the memory block and returns it.
-
#get_int(offset) ⇒ Integer
Reads a int from the offset into the memory block and returns it.
-
#get_int16(offset) ⇒ Object
Reads a int16_t from the offset into the memory block and returns it.
-
#get_int32(offset) ⇒ Object
Reads a int32_t from the offset into the memory block and returns it.
-
#get_int64(offset) ⇒ Object
Reads a int64_t from the offset into the memory block and returns it.
-
#get_int8(offset) ⇒ Object
Reads a int8_t from the offset into the memory block and returns it.
-
#get_intptr_t(offset) ⇒ Object
Reads a intptr_t from the offset into the memory block and returns it.
-
#get_long(offset) ⇒ Integer
Reads a long from the offset into the memory block and returns it.
-
#get_long_long(offset) ⇒ Integer
Reads a long long from the offset into the memory block and returns it.
-
#get_ptrdiff_t(offset) ⇒ Object
Reads a ptrdiff_t from the offset into the memory block and returns it.
-
#get_short(offset) ⇒ Integer
Reads a short from the offset into the memory block and returns it.
-
#get_signed_char(offset) ⇒ Object
Reads a signed char from the offset into the memory block and returns it.
-
#get_size_t(offset) ⇒ Object
Reads a size_t from the offset into the memory block and returns it.
-
#get_string(offset, length = nil) ⇒ String
Copies a string out of the block and returns it.
-
#get_uint16(offset) ⇒ Object
Reads a uint16_t from the offset into the memory block and returns it.
-
#get_uint32(offset) ⇒ Object
Reads a uint32_t from the offset into the memory block and returns it.
-
#get_uint64(offset) ⇒ Object
Reads a uint64_t from the offset into the memory block and returns it.
-
#get_uint8(offset) ⇒ Object
Reads a uint8_t from the offset into the memory block and returns it.
-
#get_uintptr_t(offset) ⇒ Object
Reads a uintptr_t from the offset into the memory block and returns it.
-
#get_unsigned_char(offset) ⇒ Object
Reads a unsigned char from the offset into the memory block and returns it.
-
#get_unsigned_int(offset) ⇒ Integer
Reads a unsigned int from the offset into the memory block and returns it.
-
#get_unsigned_long(offset) ⇒ Integer
Reads a unsigned long from the offset into the memory block and returns it.
-
#get_unsigned_long_long(offset) ⇒ Integer
Reads a unsigned long long from the offset into the memory block and returns it.
-
#get_unsigned_short(offset) ⇒ Integer
Reads a unsigned short from the offset into the memory block and returns it.
-
#inspect ⇒ Object
Returns a string showing the memory block’s classname, object ID, address, size, and alignment.
-
#null? ⇒ Boolean
Returns whether the memory block is pointing to a null address.
-
#realloc!(size, alignment = nil) ⇒ self
Reallocates the memory backing this pointer with a new size and optionally a new alignment.
-
#set_char(offset, value) ⇒ Object
Sets a char at the offset to the value.
-
#set_double(offset, value) ⇒ Object
Sets a double at the offset to the value.
-
#set_float(offset, value) ⇒ Object
Sets a float at the offset to the value.
-
#set_int(offset, value) ⇒ Object
Sets a int at the offset to the value.
-
#set_int16(offset, value) ⇒ Object
Sets a int16_t at the offset to the value.
-
#set_int32(offset, value) ⇒ Object
Sets a int32_t at the offset to the value.
-
#set_int64(offset, value) ⇒ Object
Sets a int64_t at the offset to the value.
-
#set_int8(offset, value) ⇒ Object
Sets a int8_t at the offset to the value.
-
#set_intptr_t(offset, value) ⇒ Object
Sets a intptr_t at the offset to the value.
-
#set_long(offset, value) ⇒ Object
Sets a long at the offset to the value.
-
#set_long_long(offset, value) ⇒ Object
Sets a long long at the offset to the value.
-
#set_ptrdiff_t(offset, value) ⇒ Object
Sets a ptrdiff_t at the offset to the value.
-
#set_short(offset, value) ⇒ Object
Sets a short at the offset to the value.
-
#set_signed_char(offset, value) ⇒ Object
Sets a signed char at the offset to the value.
-
#set_size_t(offset, value) ⇒ Object
Sets a size_t at the offset to the value.
-
#set_string(offset, value, null_terminated = false) ⇒ Object
Copies the string value into the block at the offset supplied.
-
#set_uint16(offset, value) ⇒ Object
Sets a uint16_t at the offset to the value.
-
#set_uint32(offset, value) ⇒ Object
Sets a uint32_t at the offset to the value.
-
#set_uint64(offset, value) ⇒ Object
Sets a uint64_t at the offset to the value.
-
#set_uint8(offset, value) ⇒ Object
Sets a uint8_t at the offset to the value.
-
#set_uintptr_t(offset, value) ⇒ Object
Sets a uintptr_t at the offset to the value.
-
#set_unsigned_char(offset, value) ⇒ Object
Sets a unsigned char at the offset to the value.
-
#set_unsigned_int(offset, value) ⇒ Object
Sets a unsigned int at the offset to the value.
-
#set_unsigned_long(offset, value) ⇒ Object
Sets a unsigned long at the offset to the value.
-
#set_unsigned_long_long(offset, value) ⇒ Object
Sets a unsigned long long at the offset to the value.
-
#set_unsigned_short(offset, value) ⇒ Object
Sets a unsigned short at the offset to the value.
-
#to_s(null_terminated = true) ⇒ String
Gets a string representation of the contents of this block.
Class Method Details
.alloca(size) {|memory| ... } ⇒ Object .__alloca__(size) {|memory| ... } ⇒ Object
Allocates size bytes on the stack and yields it to a block before for use, then returns the result of the block. Outside of the block, any use of the yielded memory’s address is considered undefined behavior and may lead to crashes or worse. The yielded memory is only valid for the duration of the block. If you want to preserve the memory after use, either duplicate the memory block or realloc! the memory, both of which will copy it from the stack to the heap.
The alignment of the yielded memory is always the size of a pointer.
Because of how downright evil alloca is in some situations, it is disabled by default. You must explicitly install snow-data with the –allow-alloca flag to use this function. If you’re not certain whether alloca is available for a particular installation, then you should check if the Memory class responds to it first.
if Snow::Memory.respond_to?(:__alloca__)
Snow::Memory.__alloca__(64) { |mem|
# ...
}
end
Subclasses may override alloca to provide a predefined size argument, but subclasses must never override __alloca__. It is considered bad form to implement __alloca__ using heap allocation for installations that don’t provide it.
1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 |
# File 'ext/snow-data/snow-data.c', line 1492 static VALUE sd_memory_alloca(VALUE self, VALUE sd_size) { VALUE result = Qnil; void *stack_memory = NULL; struct RData *block_data; size_t size = NUM2SIZET(sd_size); VALUE block; rb_need_block(); if (size == 0) { rb_raise(rb_eRangeError, "Size of block must be 1 or more -- zero-byte" " blocks are not permitted."); } stack_memory = alloca(size); if (stack_memory == NULL) { rb_raise(rb_eNoMemError, "Failed to allocated %zu bytes via alloca", size); } block = sd_wrap_memory(self, stack_memory, size, SIZEOF_VOIDP, SD_DO_NOT_FREE_MEMORY); block_data = RDATA(block); result = rb_yield(block); /* If the block hasn't been realloc!'d or freed, free it now if it hasn't been frozen for some reason. */ if (block_data->data == stack_memory && !block_data->dfree && !OBJ_FROZEN(block)) { sd_memory_force_free(block); } return result; } |
.malloc(size, alignment = nil) ⇒ Memory .__malloc__(size, alignment = nil) ⇒ Memory Also known as: malloc, []
Allocates a new block with the given size and alignment and returns it. If no alignment is specified, it defaults to Snow::Memory::SIZEOF_VOID_POINTER.
Raises a RangeError if either size is zero or alignment is not a power of two.
If a subclass overrides ::malloc, which is a bad idea and should not be done, then it is aliased as ::__malloc__ as well. Subclasses must never override ::__malloc__.
1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 |
# File 'ext/snow-data/snow-data.c', line 1430 static VALUE sd_memory_malloc(int argc, VALUE *argv, VALUE self) { VALUE sd_size; VALUE sd_alignment; size_t alignment; size_t size; void *data; VALUE memory; rb_scan_args(argc, argv, "11", &sd_size, &sd_alignment); /* Get size and alignment */ size = NUM2SIZET(sd_size); alignment = RTEST(sd_alignment) ? NUM2SIZET(sd_alignment) : sizeof(void *); if (!is_power_of_two(alignment)) { rb_raise(rb_eRangeError, "Alignment must be a power of two -- %zu is not a" " power of two", alignment); } else if (size < 1) { rb_raise(rb_eRangeError, "Size of block must be 1 or more -- zero-byte" " blocks are not permitted"); } /* Allocate block */ data = com_malloc(size, alignment); memory = sd_wrap_memory(self, data, size, alignment, SD_FREE_MEMORY); return memory; } |
.new(address, size, alignment = SIZEOF_VOID_POINTER) ⇒ Memory .wrap(address, size, alignment = SIZEOF_VOID_POINTER) ⇒ Memory .__wrap__(address, size, alignment = SIZEOF_VOID_POINTER) ⇒ Memory Also known as: new, wrap
Creates a new Memory object that wraps an existing pointer. Alignment is optional and defaults to the size of a pointer (Memory::SIZEOF_VOID_POINTER).
Size must be greater than zero. Zero-sized blocks are not permitted as they render most memory functionality useless and make it very difficult to ensure nothing bad is happening when you do bad things with snow-data. Because, let’s be honest with ourselves for a moment, everyone using this gem? They’re bad people. They’re very bad people.
Note that Memory objects created with this method will not attempt to free the memory they wrap, as they did not allocate it and so do not own it. If an address held by a Memory object is invalid, the Memory object is also implicitly invalid as well, though there is no way for it to check this. You are responsible for freeing any memory not allocated through ::malloc and Memory subclasses.
It is an ArgumentError to provide a size of zero, nil, or false. It is also an ArgumentError to provide a NULL (zero) address.
If a subclass overrides ::new, it is also aliased as ::wrap and ::__wrap__. Subclasses may override ::wrap or ::new but must never override ::__wrap__.
1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 |
# File 'ext/snow-data/snow-data.c', line 1377 static VALUE sd_memory_new(int argc, VALUE *argv, VALUE self) { VALUE sd_size; VALUE sd_address; VALUE sd_alignment; VALUE memory = Qnil; void *address; size_t size; size_t alignment; rb_scan_args(argc, argv, "21", &sd_address, &sd_size, &sd_alignment); address = (void *)SD_NUM_TO_INTPTR_T(sd_address); size = 0; alignment = SIZEOF_VOIDP; if (address == NULL) { rb_raise(rb_eArgError, "Address is NULL (%p).", address); } if (RTEST(sd_size)) { size = NUM2SIZET(sd_size); } else { rb_raise(rb_eArgError, "Block size is false or nil"); } if (!size) { rb_raise(rb_eArgError, "Block size must be 1 or greater"); } if (RTEST(sd_alignment)) { alignment = NUM2SIZET(sd_alignment); } memory = sd_wrap_memory(self, address, size, alignment, SD_DO_NOT_FREE_MEMORY); return memory; } |
.align_size(size_or_offset, alignment = nil) ⇒ Integer
Aligns a given size or offset to a specific alignment. If no alignment is provided, it defaults to the size of a pointer on the architecture the extension was compiled for.
See Snow::Memory::SIZEOF_VOID_POINTER for the size of a pointer.
Raises a RangeError if the alignment is not a power of two. In this case, 1 is considered a valid power of two.
1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 |
# File 'ext/snow-data/snow-data.c', line 1879 static VALUE sd_align_size(int argc, VALUE *argv, VALUE self) { VALUE sd_alignment; VALUE sd_size; size_t alignment = sizeof(void *); rb_scan_args(argc, argv, "11", &sd_size, &sd_alignment); if (RTEST(sd_alignment)) { alignment = NUM2SIZET(sd_alignment); if (!is_power_of_two(alignment)) { rb_raise(rb_eRangeError, "Alignment must be a power of two -- %zu is not" " a power of two", alignment); } } return SIZET2NUM(align_size(NUM2SIZET(sd_size), alignment)); } |
Instance Method Details
#==(other) ⇒ Object
Returns whether this and another block are equal in terms of their properties – that is, whether they have the address and bytesize. If true, the objects refer to teh same block of memory. If false, they might still overlap, refer to different chunks of memory, one might be null, etc.
79 80 81 82 83 84 85 86 87 |
# File 'lib/snow-data/memory.rb', line 79 def ==(other) return false unless other if other.kind_of?(Memory) || (other.respond_to?(:address) && other.respond_to?(:bytesize)) self.address == other.address && self.bytesize == other.bytesize else false end end |
#address ⇒ Integer
Gets the address of this memory block as an Integer.
1861 1862 1863 1864 |
# File 'ext/snow-data/snow-data.c', line 1861 static VALUE sd_memory_address(VALUE self) { return SD_UINTPTR_T_TO_NUM((uintptr_t)RDATA(self)->data); } |
#alignment ⇒ Object
The alignment in bytes of a memory block.
60 61 62 |
# File 'lib/snow-data/memory.rb', line 60 def alignment @__alignment__ end |
#bytesize ⇒ Object
The size in bytes of a memory block.
52 53 54 |
# File 'lib/snow-data/memory.rb', line 52 def bytesize @__bytesize__ end |
#copy!(source, destination_offset = nil, source_offset = nil, byte_size = nil) ⇒ self
Copies byte_size bytes from an offset in the source data to an offset into the receiver (the destination).
If either offset is nil, they default to zero.
If the byte_size is nil, it defaults to the receiver’s #bytesize.
If the source responds to #bytesize and the source’s bytesize is smaller than the size given, the source’s size is used instead of the specified or default size.
The source pointer does not have its bounds checked, as this isn’t possible for all cases. Instead, you must ensure that your source offset and byte size are both within range of the source data.
For those curious, under the hood, this uses memmove, not memcpy. So, it is possible to copy overlapping regions of memory, but it isn’t guaranteed to be as fast as a simple memcpy. Either way, if this is a concern for you, you probably shouldn’t be using Ruby.
Exceptions
-
If attempting to copy into a region that is outside the bounds of the receiver will raise a RangeError.
-
If either the receiver or the source address is NULL, it will raise an ArgumentError.
-
If the source object is neither a Data object (or a subclass thereof) or a Numerical address, it raises a TypeError.
1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 |
# File 'ext/snow-data/snow-data.c', line 1659 static VALUE sd_memory_copy(int argc, VALUE *argv, VALUE self) { VALUE sd_source; VALUE sd_destination_offset; VALUE sd_source_offset; VALUE sd_byte_size; struct RData *self_data; const uint8_t *source_pointer; uint8_t *destination_pointer; size_t source_offset; size_t destination_offset; size_t byte_size; size_t self_byte_size; #if defined(SD_WARN_ON_NO_BYTESIZE_METHOD) || defined(SD_WARN_ON_IMPLICIT_COPY_SIZE) int source_is_data = 0; #endif sd_check_null_block(self); rb_check_frozen(self); rb_scan_args(argc, argv, "13", &sd_source, &sd_destination_offset, &sd_source_offset, &sd_byte_size); /* By default, try to get an address from the object, if possible. Then use that address and don't extract it from the Data object or what have you. */ if (rb_obj_respond_to(sd_source, kSD_ID_ADDRESS, 0)) { VALUE source_address = rb_funcall2(sd_source, kSD_ID_ADDRESS, 0, 0); if (RTEST(rb_obj_is_kind_of(source_address, rb_cNumeric))) { source_pointer = (uint8_t *)SD_NUM_TO_INTPTR_T(source_address); goto sd_memory_copy_skip_data_check; } } if (RTEST(rb_obj_is_kind_of(sd_source, rb_cObject))) { /* Otherwise extract a pointer from the object if it's a Data object */ const struct RData *source_data = RDATA(sd_source); source_pointer = ((const uint8_t *)source_data->data); #if defined(SD_WARN_ON_NO_BYTESIZE_METHOD) || defined(SD_WARN_ON_IMPLICIT_COPY_SIZE) source_is_data = 1; #endif } else if (RTEST(rb_obj_is_kind_of(sd_source, rb_cNumeric))) { /* Otherwise, if it's a Numeric, try to convert what is assumed to be an address to a pointer */ source_pointer = (uint8_t *)SD_NUM_TO_INTPTR_T(sd_source); } else { rb_raise(rb_eTypeError, "Source object must be type of numeric (address) or Data- got %s", rb_obj_classname(sd_source)); } sd_memory_copy_skip_data_check: /* skip from address check */ self_data = RDATA(self); /* Check if the source pointer is NULL -- error if it is (the destination pointer is checked by sd_check_null_block above). */ if (source_pointer == NULL) { rb_raise(rb_eArgError, "Source pointer is NULL"); } /* Grab data from ruby values and offset the source pointer. */ source_offset = RTEST(sd_source_offset) ? NUM2SIZET(sd_source_offset) : 0; destination_offset = RTEST(sd_destination_offset) ? NUM2SIZET(sd_destination_offset) : 0; destination_pointer = (uint8_t *)self_data->data + destination_offset; self_byte_size = NUM2SIZET(rb_ivar_get(self, kSD_IVAR_BYTESIZE)); source_pointer += source_offset; if (self_byte_size == 0) { /* If self is a zero-length block, do not try to copy. It's just not sane to attempt it here since we can't do any bounds checking, even if the bounds might be arbitrarily specified (in which case I'd just be shooting myself in the foot if I did that and trying to circumvent the anti-foot-shot protections). */ rb_raise(rb_eRuntimeError, "self.bytesize == 0 -- cannot safely copy to this block"); } else if (!RTEST(sd_byte_size)) { /* If not copy size is specified, use self_byte_size and just try to cram as much in there as is feasible. Truncate self_byte_size as needed for the offset. */ byte_size = self_byte_size - destination_offset; #ifdef SD_WARN_ON_IMPLICIT_COPY_SIZE if (!source_is_data) { rb_warning( "Copying %zu bytes from non-Data memory address %p without explicit size", byte_size, source_pointer); } #endif } else { /* User-specified size */ byte_size = NUM2SIZET(sd_byte_size); } /* If the source responds to bytesize, check if the copy is within bounds for the source. If it's out of bounds, raise a RangeError, otherwise optionally emit a warning that bounds checking doesn't work for this source. */ if (rb_obj_respond_to(sd_source, kSD_ID_BYTESIZE, 0)) { size_t source_size = NUM2SIZET(rb_funcall2(sd_source, kSD_ID_BYTESIZE, 0, 0)); if (source_offset > source_size || (source_offset + byte_size) > source_size || (source_offset + byte_size) < source_offset) { rb_raise(rb_eRangeError, "Attempt to copy out of source bounds"); } } #ifdef SD_WARN_ON_NO_BYTESIZE_METHOD else if (source_is_data) { rb_warning( "Copying from Data object pointer %p that does not respond to #bytesize" " -- this operation is not bounds-checked.", source_pointer); } #endif if ((destination_offset + byte_size) > self_byte_size || (destination_offset + byte_size) < destination_offset) { rb_raise(rb_eRangeError, "Offset %zu with byte size %zu is out of bounds of self", destination_offset, byte_size); } #ifdef SD_VERBOSE_COPY_LOG /* Emit some debugging info just in case things go completely haywire and you really need to know what's going on. */ fprintf(stderr, "# copy! ----------------------------------------\n" "# destination_pointer = %p" "\n" "# source_pointer = %p" "\n" "# destination_offset = %zu" "\n" "# source_offset = %zu" "\n" "# byte_size = %zu" "\n" "# self_byte_size = %zu" "\n" "# source.class = %s" "\n" "# self.class = %s" "\n" "# --------------------------------------- /copy!\n", destination_pointer - destination_offset, source_pointer - source_offset, destination_offset, source_offset, byte_size, self_byte_size, rb_obj_classname(sd_source), rb_obj_classname(self)); #endif /* And skip a copy if we can */ if (byte_size == 0 || source_pointer == destination_pointer) { return self; } memmove(destination_pointer, source_pointer, byte_size); return self; } |
#dup ⇒ Object
Creates a new block of memory with the same class, size, and alignment; copies the receiver’s data to the new block; and returns the new block.
103 104 105 106 |
# File 'lib/snow-data/memory.rb', line 103 def dup new_self = self.class.__malloc__(self.bytesize, self.alignment) new_self.copy!(self, 0, 0, self.bytesize) end |
#free! ⇒ self
Frees any memory owned by the object. This is a convenience function for when you want to free the memory ahead of the object being collected by the GC.
1619 1620 1621 1622 1623 1624 |
# File 'ext/snow-data/snow-data.c', line 1619 static VALUE sd_memory_free(VALUE self) { rb_check_frozen(self); sd_memory_force_free(self); return self; } |
#get_char(offset) ⇒ String
Reads a char from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 |
# File 'ext/snow-data/snow-data.c', line 1102 static VALUE sd_get_char(VALUE self, VALUE sd_offset) { typedef char conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_CHAR_TO_NUM(value); } |
#get_double(offset) ⇒ Object
Reads a double from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
907 908 909 910 911 912 913 914 915 916 |
# File 'ext/snow-data/snow-data.c', line 907 static VALUE sd_get_double(VALUE self, VALUE sd_offset) { typedef double conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_DOUBLE_TO_NUM(value); } |
#get_float(offset) ⇒ Float
Reads a float from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
868 869 870 871 872 873 874 875 876 877 |
# File 'ext/snow-data/snow-data.c', line 868 static VALUE sd_get_float(VALUE self, VALUE sd_offset) { typedef float conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_FLOAT_TO_NUM(value); } |
#get_int(offset) ⇒ Integer
Reads a int from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
946 947 948 949 950 951 952 953 954 955 |
# File 'ext/snow-data/snow-data.c', line 946 static VALUE sd_get_int(VALUE self, VALUE sd_offset) { typedef int conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_INT_TO_NUM(value); } |
#get_int16(offset) ⇒ Object
Reads a int16_t from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
283 284 285 286 287 288 289 290 291 292 |
# File 'ext/snow-data/snow-data.c', line 283 static VALUE sd_get_int16(VALUE self, VALUE sd_offset) { typedef int16_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_INT16_TO_NUM(value); } |
#get_int32(offset) ⇒ Object
Reads a int32_t from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
322 323 324 325 326 327 328 329 330 331 |
# File 'ext/snow-data/snow-data.c', line 322 static VALUE sd_get_int32(VALUE self, VALUE sd_offset) { typedef int32_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_INT32_TO_NUM(value); } |
#get_int64(offset) ⇒ Object
Reads a int64_t from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
361 362 363 364 365 366 367 368 369 370 |
# File 'ext/snow-data/snow-data.c', line 361 static VALUE sd_get_int64(VALUE self, VALUE sd_offset) { typedef int64_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_INT64_TO_NUM(value); } |
#get_int8(offset) ⇒ Object
Reads a int8_t from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
244 245 246 247 248 249 250 251 252 253 |
# File 'ext/snow-data/snow-data.c', line 244 static VALUE sd_get_int8(VALUE self, VALUE sd_offset) { typedef int8_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_INT8_TO_NUM(value); } |
#get_intptr_t(offset) ⇒ Object
Reads a intptr_t from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
634 635 636 637 638 639 640 641 642 643 |
# File 'ext/snow-data/snow-data.c', line 634 static VALUE sd_get_intptr_t(VALUE self, VALUE sd_offset) { typedef intptr_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_INTPTR_T_TO_NUM(value); } |
#get_long(offset) ⇒ Integer
Reads a long from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
712 713 714 715 716 717 718 719 720 721 |
# File 'ext/snow-data/snow-data.c', line 712 static VALUE sd_get_long(VALUE self, VALUE sd_offset) { typedef long conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_LONG_TO_NUM(value); } |
#get_long_long(offset) ⇒ Integer
Reads a long long from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
751 752 753 754 755 756 757 758 759 760 |
# File 'ext/snow-data/snow-data.c', line 751 static VALUE sd_get_long_long(VALUE self, VALUE sd_offset) { typedef long long conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_LONG_LONG_TO_NUM(value); } |
#get_ptrdiff_t(offset) ⇒ Object
Reads a ptrdiff_t from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
595 596 597 598 599 600 601 602 603 604 |
# File 'ext/snow-data/snow-data.c', line 595 static VALUE sd_get_ptrdiff_t(VALUE self, VALUE sd_offset) { typedef ptrdiff_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_PTRDIFF_T_TO_NUM(value); } |
#get_short(offset) ⇒ Integer
Reads a short from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 |
# File 'ext/snow-data/snow-data.c', line 1024 static VALUE sd_get_short(VALUE self, VALUE sd_offset) { typedef short conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_SHORT_TO_NUM(value); } |
#get_signed_char(offset) ⇒ Object
Reads a signed char from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 |
# File 'ext/snow-data/snow-data.c', line 1180 static VALUE sd_get_signed_char(VALUE self, VALUE sd_offset) { typedef signed char conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_SIGNED_CHAR_TO_NUM(value); } |
#get_size_t(offset) ⇒ Object
Reads a size_t from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
556 557 558 559 560 561 562 563 564 565 |
# File 'ext/snow-data/snow-data.c', line 556 static VALUE sd_get_size_t(VALUE self, VALUE sd_offset) { typedef size_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_SIZE_T_TO_NUM(value); } |
#get_string(offset, length = nil) ⇒ String
Copies a string out of the block and returns it. The length argument is used to specify how the string is copied.
If length is nil, the string is extracted from offset up to the first null character. If length is -1, it extracts all characters from offset onward in the string and returns it. Otherwise, for any other length, it tries to copy length characters from the block before the end of the block.
This method does not work on zero-length blocks.
1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 |
# File 'ext/snow-data/snow-data.c', line 1224 static VALUE sd_get_string(int argc, VALUE *argv, VALUE self) { VALUE sd_offset; VALUE sd_length; size_t offset; size_t length = ~(size_t)0; size_t self_length = NUM2SIZET(rb_ivar_get(self, kSD_IVAR_BYTESIZE)); const uint8_t *data = DATA_PTR(self); sd_check_null_block(self); rb_scan_args(argc, argv, "11", &sd_offset, &sd_length); offset = NUM2SIZET(sd_offset); if (offset >= self_length) { return rb_str_new("", 0); } if (RTEST(sd_length)) { length = NUM2SIZET(sd_length); if (length == ~(size_t)0 || (offset + length) > self_length || (offset + length) < offset) { length = self_length - offset; } } else { for (length = offset; length < self_length && data[length]; ++length) ; length -= offset; } return rb_str_new((const char *)(data + offset), length); } |
#get_uint16(offset) ⇒ Object
Reads a uint16_t from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
439 440 441 442 443 444 445 446 447 448 |
# File 'ext/snow-data/snow-data.c', line 439 static VALUE sd_get_uint16(VALUE self, VALUE sd_offset) { typedef uint16_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_UINT16_TO_NUM(value); } |
#get_uint32(offset) ⇒ Object
Reads a uint32_t from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
478 479 480 481 482 483 484 485 486 487 |
# File 'ext/snow-data/snow-data.c', line 478 static VALUE sd_get_uint32(VALUE self, VALUE sd_offset) { typedef uint32_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_UINT32_TO_NUM(value); } |
#get_uint64(offset) ⇒ Object
Reads a uint64_t from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
517 518 519 520 521 522 523 524 525 526 |
# File 'ext/snow-data/snow-data.c', line 517 static VALUE sd_get_uint64(VALUE self, VALUE sd_offset) { typedef uint64_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_UINT64_TO_NUM(value); } |
#get_uint8(offset) ⇒ Object
Reads a uint8_t from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
400 401 402 403 404 405 406 407 408 409 |
# File 'ext/snow-data/snow-data.c', line 400 static VALUE sd_get_uint8(VALUE self, VALUE sd_offset) { typedef uint8_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_UINT8_TO_NUM(value); } |
#get_uintptr_t(offset) ⇒ Object
Reads a uintptr_t from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
673 674 675 676 677 678 679 680 681 682 |
# File 'ext/snow-data/snow-data.c', line 673 static VALUE sd_get_uintptr_t(VALUE self, VALUE sd_offset) { typedef uintptr_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_UINTPTR_T_TO_NUM(value); } |
#get_unsigned_char(offset) ⇒ Object
Reads a unsigned char from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 |
# File 'ext/snow-data/snow-data.c', line 1141 static VALUE sd_get_unsigned_char(VALUE self, VALUE sd_offset) { typedef unsigned char conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_UNSIGNED_CHAR_TO_NUM(value); } |
#get_unsigned_int(offset) ⇒ Integer
Reads a unsigned int from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
985 986 987 988 989 990 991 992 993 994 |
# File 'ext/snow-data/snow-data.c', line 985 static VALUE sd_get_unsigned_int(VALUE self, VALUE sd_offset) { typedef unsigned int conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_UNSIGNED_INT_TO_NUM(value); } |
#get_unsigned_long(offset) ⇒ Integer
Reads a unsigned long from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
790 791 792 793 794 795 796 797 798 799 |
# File 'ext/snow-data/snow-data.c', line 790 static VALUE sd_get_unsigned_long(VALUE self, VALUE sd_offset) { typedef unsigned long conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_UNSIGNED_LONG_TO_NUM(value); } |
#get_unsigned_long_long(offset) ⇒ Integer
Reads a unsigned long long from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
829 830 831 832 833 834 835 836 837 838 |
# File 'ext/snow-data/snow-data.c', line 829 static VALUE sd_get_unsigned_long_long(VALUE self, VALUE sd_offset) { typedef unsigned long long conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_UNSIGNED_LONG_LONG_TO_NUM(value); } |
#get_unsigned_short(offset) ⇒ Integer
Reads a unsigned short from the offset into the memory block and returns it. The offset is not bounds-checked and it is possible to read outside of bounds, which is considered undefined behavior and may crash or do other horrible things.
1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 |
# File 'ext/snow-data/snow-data.c', line 1063 static VALUE sd_get_unsigned_short(VALUE self, VALUE sd_offset) { typedef unsigned short conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset); return SD_UNSIGNED_SHORT_TO_NUM(value); } |
#inspect ⇒ Object
Returns a string showing the memory block’s classname, object ID, address, size, and alignment.
94 95 96 |
# File 'lib/snow-data/memory.rb', line 94 def inspect "<#{self.class}:0x#{__id__.to_s(16).rjust(14, ?0)} *0x#{self.address.to_s(16).rjust(14, ?0)}:#{self.bytesize}:#{self.alignment}>" end |
#null? ⇒ Boolean
Returns whether the memory block is pointing to a null address.
68 69 70 |
# File 'lib/snow-data/memory.rb', line 68 def null? self.address == 0 end |
#realloc!(size, alignment = nil) ⇒ self
Reallocates the memory backing this pointer with a new size and optionally a new alignment. If the new size is the same as the old size, the method returns early and nothing is reallocated.
If a new alignment is specified, the memory will be reallocated regardless of whether the new and old sizes are the same. If no alignment is specified, the memory’s previous alignment is used.
If the block for this memory was previously freed or the block is not owner by this object, a new block is allocated and the memory takes ownership of it. It is fine to realloc! on a previously freed block.
Raises a RangeError if either size is zero or alignment is not a power of two.
1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 |
# File 'ext/snow-data/snow-data.c', line 1548 static VALUE sd_memory_realloc(int argc, VALUE *argv, VALUE self) { struct RData *data; void *new_data; size_t size; size_t prev_size; size_t prev_align; size_t alignment; VALUE sd_size; VALUE sd_alignment; /* Don't check for null/zero length here, as it is safe to reuse a memory via realloc!. It's less safe for structs and arrays, but you just have to do the sane thing in most cases. Granted, I'm a hypocrite for you need to do the sane thing after writing this gem. */ rb_check_frozen(self); rb_scan_args(argc, argv, "11", &sd_size, &sd_alignment); size = NUM2SIZET(sd_size); prev_align = alignment = NUM2SIZET(rb_ivar_get(self, kSD_IVAR_ALIGNMENT)); prev_size = NUM2SIZET(rb_ivar_get(self, kSD_IVAR_BYTESIZE)); if (RTEST(sd_alignment)) { alignment = NUM2SIZET(sd_alignment); } if (prev_size == size && alignment == prev_align) { return self; } else if (!is_power_of_two(alignment)) { rb_raise(rb_eRangeError, "Alignment must be a power of two -- %zu is not a" " power of two", alignment); } else if (size < 1) { rb_raise(rb_eRangeError, "Size of block must be 1 or more -- zero-byte" " blocks are not permitted"); } data = RDATA(self); new_data = com_malloc(size, alignment); if (data->data && prev_size > 0) { const size_t copy_sizes[2] = { prev_size, size }; memcpy(new_data, data->data, copy_sizes[prev_size > size]); } if (data->dfree) { data->dfree(data->data); } else if (data->data) { rb_warning("realloc called on unowned pointer %p -- allocating new block" " and memcpying contents (size: %zd bytes), but original block will" " not be freed.", data->data, prev_size); } data->data = new_data; data->dfree = com_free; rb_ivar_set(self, kSD_IVAR_BYTESIZE, SIZET2NUM(size)); rb_ivar_set(self, kSD_IVAR_ALIGNMENT, SIZET2NUM(alignment)); return self; } |
#set_char(offset, value) ⇒ Object
Sets a char at the offset to the value. Returns the assigned value.
1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 |
# File 'ext/snow-data/snow-data.c', line 1119 static VALUE sd_set_char(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef char conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_CHAR(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_double(offset, value) ⇒ Object
Sets a double at the offset to the value. Returns the assigned value.
924 925 926 927 928 929 930 931 932 933 934 935 |
# File 'ext/snow-data/snow-data.c', line 924 static VALUE sd_set_double(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef double conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_DOUBLE(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_float(offset, value) ⇒ Object
Sets a float at the offset to the value. Returns the assigned value.
885 886 887 888 889 890 891 892 893 894 895 896 |
# File 'ext/snow-data/snow-data.c', line 885 static VALUE sd_set_float(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef float conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_FLOAT(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_int(offset, value) ⇒ Object
Sets a int at the offset to the value. Returns the assigned value.
963 964 965 966 967 968 969 970 971 972 973 974 |
# File 'ext/snow-data/snow-data.c', line 963 static VALUE sd_set_int(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef int conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_INT(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_int16(offset, value) ⇒ Object
Sets a int16_t at the offset to the value. Returns the assigned value.
300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'ext/snow-data/snow-data.c', line 300 static VALUE sd_set_int16(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef int16_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_INT16(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_int32(offset, value) ⇒ Object
Sets a int32_t at the offset to the value. Returns the assigned value.
339 340 341 342 343 344 345 346 347 348 349 350 |
# File 'ext/snow-data/snow-data.c', line 339 static VALUE sd_set_int32(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef int32_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_INT32(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_int64(offset, value) ⇒ Object
Sets a int64_t at the offset to the value. Returns the assigned value.
378 379 380 381 382 383 384 385 386 387 388 389 |
# File 'ext/snow-data/snow-data.c', line 378 static VALUE sd_set_int64(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef int64_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_INT64(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_int8(offset, value) ⇒ Object
Sets a int8_t at the offset to the value. Returns the assigned value.
261 262 263 264 265 266 267 268 269 270 271 272 |
# File 'ext/snow-data/snow-data.c', line 261 static VALUE sd_set_int8(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef int8_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_INT8(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_intptr_t(offset, value) ⇒ Object
Sets a intptr_t at the offset to the value. Returns the assigned value.
651 652 653 654 655 656 657 658 659 660 661 662 |
# File 'ext/snow-data/snow-data.c', line 651 static VALUE sd_set_intptr_t(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef intptr_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_INTPTR_T(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_long(offset, value) ⇒ Object
Sets a long at the offset to the value. Returns the assigned value.
729 730 731 732 733 734 735 736 737 738 739 740 |
# File 'ext/snow-data/snow-data.c', line 729 static VALUE sd_set_long(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef long conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_LONG(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_long_long(offset, value) ⇒ Object
Sets a long long at the offset to the value. Returns the assigned value.
768 769 770 771 772 773 774 775 776 777 778 779 |
# File 'ext/snow-data/snow-data.c', line 768 static VALUE sd_set_long_long(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef long long conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_LONG_LONG(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_ptrdiff_t(offset, value) ⇒ Object
Sets a ptrdiff_t at the offset to the value. Returns the assigned value.
612 613 614 615 616 617 618 619 620 621 622 623 |
# File 'ext/snow-data/snow-data.c', line 612 static VALUE sd_set_ptrdiff_t(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef ptrdiff_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_PTRDIFF_T(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_short(offset, value) ⇒ Object
Sets a short at the offset to the value. Returns the assigned value.
1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 |
# File 'ext/snow-data/snow-data.c', line 1041 static VALUE sd_set_short(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef short conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_SHORT(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_signed_char(offset, value) ⇒ Object
Sets a signed char at the offset to the value. Returns the assigned value.
1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 |
# File 'ext/snow-data/snow-data.c', line 1197 static VALUE sd_set_signed_char(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef signed char conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_SIGNED_CHAR(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_size_t(offset, value) ⇒ Object
Sets a size_t at the offset to the value. Returns the assigned value.
573 574 575 576 577 578 579 580 581 582 583 584 |
# File 'ext/snow-data/snow-data.c', line 573 static VALUE sd_set_size_t(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef size_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_SIZE_T(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_string(offset, value, null_terminated = false) ⇒ Object
Copies the string value into the block at the offset supplied.
If null_terminated is true, it will always write a null-terminating character if it fits. This means that you need at least string.bytesize + 1 bytes available from the offset onwards to fully story a string, otherwise the string’s contents will be truncated to fit the null-terminating character.
If null_terminated is false, no null character is written and only the string bytes are copied to the block. If the full string does not fit, it will be truncated.
1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 |
# File 'ext/snow-data/snow-data.c', line 1304 static VALUE sd_set_string(int argc, VALUE *argv, VALUE self) { VALUE sd_offset, sd_value, sd_null_terminated; sd_check_null_block(self); rb_check_frozen(self); rb_scan_args(argc, argv, "21", &sd_offset, &sd_value, &sd_null_terminated); return sd_set_string_nullterm(self, sd_offset, sd_value, !!RTEST(sd_null_terminated)); } |
#set_uint16(offset, value) ⇒ Object
Sets a uint16_t at the offset to the value. Returns the assigned value.
456 457 458 459 460 461 462 463 464 465 466 467 |
# File 'ext/snow-data/snow-data.c', line 456 static VALUE sd_set_uint16(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef uint16_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_UINT16(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_uint32(offset, value) ⇒ Object
Sets a uint32_t at the offset to the value. Returns the assigned value.
495 496 497 498 499 500 501 502 503 504 505 506 |
# File 'ext/snow-data/snow-data.c', line 495 static VALUE sd_set_uint32(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef uint32_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_UINT32(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_uint64(offset, value) ⇒ Object
Sets a uint64_t at the offset to the value. Returns the assigned value.
534 535 536 537 538 539 540 541 542 543 544 545 |
# File 'ext/snow-data/snow-data.c', line 534 static VALUE sd_set_uint64(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef uint64_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_UINT64(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_uint8(offset, value) ⇒ Object
Sets a uint8_t at the offset to the value. Returns the assigned value.
417 418 419 420 421 422 423 424 425 426 427 428 |
# File 'ext/snow-data/snow-data.c', line 417 static VALUE sd_set_uint8(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef uint8_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_UINT8(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_uintptr_t(offset, value) ⇒ Object
Sets a uintptr_t at the offset to the value. Returns the assigned value.
690 691 692 693 694 695 696 697 698 699 700 701 |
# File 'ext/snow-data/snow-data.c', line 690 static VALUE sd_set_uintptr_t(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef uintptr_t conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_UINTPTR_T(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_unsigned_char(offset, value) ⇒ Object
Sets a unsigned char at the offset to the value. Returns the assigned value.
1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 |
# File 'ext/snow-data/snow-data.c', line 1158 static VALUE sd_set_unsigned_char(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef unsigned char conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_UNSIGNED_CHAR(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_unsigned_int(offset, value) ⇒ Object
Sets a unsigned int at the offset to the value. Returns the assigned value.
1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 |
# File 'ext/snow-data/snow-data.c', line 1002 static VALUE sd_set_unsigned_int(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef unsigned int conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_UNSIGNED_INT(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_unsigned_long(offset, value) ⇒ Object
Sets a unsigned long at the offset to the value. Returns the assigned value.
807 808 809 810 811 812 813 814 815 816 817 818 |
# File 'ext/snow-data/snow-data.c', line 807 static VALUE sd_set_unsigned_long(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef unsigned long conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_UNSIGNED_LONG(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_unsigned_long_long(offset, value) ⇒ Object
Sets a unsigned long long at the offset to the value. Returns the assigned value.
846 847 848 849 850 851 852 853 854 855 856 857 |
# File 'ext/snow-data/snow-data.c', line 846 static VALUE sd_set_unsigned_long_long(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef unsigned long long conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_UNSIGNED_LONG_LONG(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#set_unsigned_short(offset, value) ⇒ Object
Sets a unsigned short at the offset to the value. Returns the assigned value.
1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 |
# File 'ext/snow-data/snow-data.c', line 1080 static VALUE sd_set_unsigned_short(VALUE self, VALUE sd_offset, VALUE sd_value) { typedef unsigned short conv_type_t; const size_t offset = NUM2SIZET(sd_offset); conv_type_t value; sd_check_block_bounds(self, offset, sizeof(conv_type_t)); sd_check_null_block(self); rb_check_frozen(self); value = (conv_type_t)SD_NUM_TO_UNSIGNED_SHORT(sd_value); *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value; return sd_value; } |
#to_s(null_terminated = true) ⇒ String
Gets a string representation of the contents of this block. If null_terminated is true (or nil), the returned string will end before the first null character.
1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 |
# File 'ext/snow-data/snow-data.c', line 1835 static VALUE sd_memory_to_s(int argc, VALUE *argv, VALUE self) { VALUE null_terminated; size_t byte_size = NUM2SIZET(rb_ivar_get(self, kSD_IVAR_BYTESIZE)); const char *data = DATA_PTR(self); sd_check_null_block(self); rb_scan_args(argc, argv, "01", &null_terminated); if (null_terminated == Qnil || RTEST(null_terminated)) { size_t string_length = 0; for (; string_length < byte_size && data[string_length]; ++string_length) ; byte_size = string_length; } return rb_str_new(data, byte_size); } |