14 #include "internal/string.h"
15 #include "internal/bits.h"
16 #include "internal/error.h"
19 VALUE rb_eIOBufferLockedError;
20 VALUE rb_eIOBufferAllocationError;
21 VALUE rb_eIOBufferAccessError;
22 VALUE rb_eIOBufferInvalidatedError;
24 size_t RUBY_IO_BUFFER_PAGE_SIZE;
25 size_t RUBY_IO_BUFFER_DEFAULT_SIZE;
36 enum rb_io_buffer_flags flags;
46 io_buffer_map_memory(
size_t size)
49 void * base = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
55 void * base = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
57 if (base == MAP_FAILED) {
66 io_buffer_map_file(
struct rb_io_buffer *data,
int descriptor,
size_t size, off_t offset,
enum rb_io_buffer_flags flags)
69 HANDLE file = (HANDLE)_get_osfhandle(descriptor);
70 if (!file)
rb_sys_fail(
"io_buffer_map_descriptor:_get_osfhandle");
72 DWORD protect = PAGE_READONLY, access = FILE_MAP_READ;
74 if (flags & RB_IO_BUFFER_READONLY) {
75 data->flags |= RB_IO_BUFFER_READONLY;
78 protect = PAGE_READWRITE;
79 access = FILE_MAP_WRITE;
82 HANDLE mapping = CreateFileMapping(file, NULL, protect, 0, 0, NULL);
83 if (!mapping)
rb_sys_fail(
"io_buffer_map_descriptor:CreateFileMapping");
85 if (flags & RB_IO_BUFFER_PRIVATE) {
86 access |= FILE_MAP_COPY;
87 data->flags |= RB_IO_BUFFER_PRIVATE;
90 data->flags |= RB_IO_BUFFER_EXTERNAL;
93 void *base = MapViewOfFile(mapping, access, (DWORD)(offset >> 32), (DWORD)(offset & 0xFFFFFFFF), size);
100 data->mapping = mapping;
102 int protect = PROT_READ, access = 0;
104 if (flags & RB_IO_BUFFER_READONLY) {
105 data->flags |= RB_IO_BUFFER_READONLY;
108 protect |= PROT_WRITE;
111 if (flags & RB_IO_BUFFER_PRIVATE) {
112 data->flags |= RB_IO_BUFFER_PRIVATE;
116 data->flags |= RB_IO_BUFFER_EXTERNAL;
117 access |= MAP_SHARED;
120 void *base = mmap(NULL, size, protect, access, descriptor, offset);
122 if (base == MAP_FAILED) {
130 data->flags |= RB_IO_BUFFER_MAPPED;
134 io_buffer_unmap(
void* base,
size_t size)
137 VirtualFree(base, 0, MEM_RELEASE);
144 io_buffer_experimental(
void)
146 static int warned = 0;
154 "IO::Buffer is experimental and both the Ruby and C interface may change in the future!"
165 data->mapping = NULL;
171 io_buffer_initialize(
struct rb_io_buffer *data,
void *base,
size_t size,
enum rb_io_buffer_flags flags,
VALUE source)
178 if (flags & RB_IO_BUFFER_INTERNAL) {
179 base = calloc(size, 1);
181 else if (flags & RB_IO_BUFFER_MAPPED) {
182 base = io_buffer_map_memory(size);
186 rb_raise(rb_eIOBufferAllocationError,
"Could not allocate buffer!");
196 data->source = source;
203 if (data->flags & RB_IO_BUFFER_INTERNAL) {
207 if (data->flags & RB_IO_BUFFER_MAPPED) {
208 io_buffer_unmap(data->base, data->size);
221 CloseHandle(data->mapping);
222 data->mapping = NULL;
236 rb_io_buffer_type_mark(
void *_data)
243 rb_io_buffer_type_free(
void *_data)
247 io_buffer_free(data);
253 rb_io_buffer_type_size(
const void *_data)
268 .dmark = rb_io_buffer_type_mark,
269 .dfree = rb_io_buffer_type_free,
270 .dsize = rb_io_buffer_type_size,
273 .flags = RUBY_TYPED_FREE_IMMEDIATELY,
277 rb_io_buffer_type_allocate(
VALUE self)
282 io_buffer_zero(data);
288 io_buffer_for_make_instance(
VALUE klass,
VALUE string)
290 VALUE instance = rb_io_buffer_type_allocate(klass);
295 enum rb_io_buffer_flags flags = RB_IO_BUFFER_EXTERNAL;
298 flags |= RB_IO_BUFFER_READONLY;
312 io_buffer_for_yield_instance(
VALUE _arguments) {
317 arguments->instance = io_buffer_for_make_instance(arguments->klass, arguments->string);
319 return rb_yield(arguments->instance);
323 io_buffer_for_yield_instance_ensure(
VALUE _arguments)
327 if (arguments->instance !=
Qnil) {
328 rb_io_buffer_free(arguments->instance);
372 rb_io_buffer_type_for(
VALUE klass,
VALUE string)
385 return rb_ensure(io_buffer_for_yield_instance, (
VALUE)&arguments, io_buffer_for_yield_instance_ensure, (
VALUE)&arguments);
388 string = rb_str_tmp_frozen_acquire(
string);
389 return io_buffer_for_make_instance(klass,
string);
394 rb_io_buffer_new(
void *base,
size_t size,
enum rb_io_buffer_flags flags)
396 VALUE instance = rb_io_buffer_type_allocate(rb_cIOBuffer);
401 io_buffer_initialize(data, base, size, flags,
Qnil);
407 rb_io_buffer_map(
VALUE io,
size_t size, off_t offset,
enum rb_io_buffer_flags flags)
409 io_buffer_experimental();
411 VALUE instance = rb_io_buffer_type_allocate(rb_cIOBuffer);
418 io_buffer_map_file(data, descriptor, size, offset, flags);
462 io_buffer_map(
int argc,
VALUE *argv,
VALUE klass)
464 if (argc < 1 || argc > 4) {
465 rb_error_arity(argc, 2, 4);
472 if (argc >= 2 && !
RB_NIL_P(argv[1])) {
483 else if ((uintmax_t)file_size > SIZE_MAX) {
488 size = (size_t)file_size;
497 enum rb_io_buffer_flags flags = 0;
502 return rb_io_buffer_map(io, size, offset, flags);
506 static inline enum rb_io_buffer_flags
507 io_flags_for_size(
size_t size)
509 if (size >= RUBY_IO_BUFFER_PAGE_SIZE) {
510 return RB_IO_BUFFER_MAPPED;
513 return RB_IO_BUFFER_INTERNAL;
544 rb_io_buffer_initialize(
int argc,
VALUE *argv,
VALUE self)
546 io_buffer_experimental();
548 if (argc < 0 || argc > 2) {
549 rb_error_arity(argc, 0, 2);
560 size = RUBY_IO_BUFFER_DEFAULT_SIZE;
563 enum rb_io_buffer_flags flags = 0;
568 flags |= io_flags_for_size(size);
571 io_buffer_initialize(data, NULL, size, flags,
Qnil);
577 io_buffer_validate_slice(
VALUE source,
void *base,
size_t size)
579 void *source_base = NULL;
580 size_t source_size = 0;
586 rb_io_buffer_get_bytes(source, &source_base, &source_size);
590 if (source_base == NULL)
return 0;
593 if (base < source_base)
return 0;
595 const void *source_end = (
char*)source_base + source_size;
596 const void *end = (
char*)base + size;
599 if (end > source_end)
return 0;
608 if (data->source !=
Qnil) {
610 return io_buffer_validate_slice(data->source, data->base, data->size);
628 rb_io_buffer_to_s(
VALUE self)
636 rb_str_catf(result,
" %p+%"PRIdSIZE, data->base, data->size);
638 if (data->base == NULL) {
642 if (data->flags & RB_IO_BUFFER_EXTERNAL) {
646 if (data->flags & RB_IO_BUFFER_INTERNAL) {
650 if (data->flags & RB_IO_BUFFER_MAPPED) {
654 if (data->flags & RB_IO_BUFFER_LOCKED) {
658 if (data->flags & RB_IO_BUFFER_READONLY) {
662 if (data->source !=
Qnil) {
666 if (!io_buffer_validate(data)) {
674 io_buffer_hexdump(
VALUE string,
size_t width,
char *base,
size_t size,
int first)
676 char *text = alloca(width+1);
679 for (
size_t offset = 0; offset < size; offset += width) {
680 memset(text,
'\0', width);
688 for (
size_t i = 0; i < width; i += 1) {
689 if (offset+i < size) {
690 unsigned char value = ((
unsigned char*)base)[offset+i];
692 if (value < 127 && isprint(value)) {
693 text[i] = (char)value;
713 rb_io_buffer_hexdump(
VALUE self)
720 if (io_buffer_validate(data) && data->base) {
723 io_buffer_hexdump(result, 16, data->base, data->size, 1);
730 rb_io_buffer_inspect(
VALUE self)
735 VALUE result = rb_io_buffer_to_s(
self);
737 if (io_buffer_validate(data)) {
739 if (data->size <= 256) {
740 io_buffer_hexdump(result, 16, data->base, data->size, 0);
755 rb_io_buffer_size(
VALUE self)
773 rb_io_buffer_valid_p(
VALUE self)
778 return RBOOL(io_buffer_validate(data));
789 rb_io_buffer_null_p(
VALUE self)
794 return RBOOL(data->base == NULL);
810 rb_io_buffer_empty_p(
VALUE self)
815 return RBOOL(data->size == 0);
819 rb_io_buffer_external_p(
VALUE self)
824 return RBOOL(data->flags & RB_IO_BUFFER_EXTERNAL);
845 rb_io_buffer_internal_p(
VALUE self)
850 return RBOOL(data->flags & RB_IO_BUFFER_INTERNAL);
868 rb_io_buffer_mapped_p(
VALUE self)
873 return RBOOL(data->flags & RB_IO_BUFFER_MAPPED);
892 rb_io_buffer_locked_p(
VALUE self)
897 return RBOOL(data->flags & RB_IO_BUFFER_LOCKED);
910 rb_io_buffer_readonly_p(
VALUE self)
915 return data->flags & RB_IO_BUFFER_READONLY;
919 io_buffer_readonly_p(
VALUE self)
921 return RBOOL(rb_io_buffer_readonly_p(
self));
925 rb_io_buffer_lock(
VALUE self)
930 if (data->flags & RB_IO_BUFFER_LOCKED) {
931 rb_raise(rb_eIOBufferLockedError,
"Buffer already locked!");
934 data->flags |= RB_IO_BUFFER_LOCKED;
940 rb_io_buffer_unlock(
VALUE self)
945 if (!(data->flags & RB_IO_BUFFER_LOCKED)) {
946 rb_raise(rb_eIOBufferLockedError,
"Buffer not locked!");
949 data->flags &= ~RB_IO_BUFFER_LOCKED;
955 rb_io_buffer_try_unlock(
VALUE self)
960 if (data->flags & RB_IO_BUFFER_LOCKED) {
961 data->flags &= ~RB_IO_BUFFER_LOCKED;
999 rb_io_buffer_locked(
VALUE self)
1004 if (data->flags & RB_IO_BUFFER_LOCKED) {
1005 rb_raise(rb_eIOBufferLockedError,
"Buffer already locked!");
1008 data->flags |= RB_IO_BUFFER_LOCKED;
1012 data->flags &= ~RB_IO_BUFFER_LOCKED;
1044 rb_io_buffer_free(
VALUE self)
1049 if (data->flags & RB_IO_BUFFER_LOCKED) {
1050 rb_raise(rb_eIOBufferLockedError,
"Buffer is locked!");
1053 io_buffer_free(data);
1059 io_buffer_validate_range(
struct rb_io_buffer *data,
size_t offset,
size_t length)
1061 if (offset + length > data->size) {
1115 io_buffer_validate_range(data, offset, length);
1121 slice->base = (
char*)data->base + offset;
1122 slice->size = length;
1125 if (data->source !=
Qnil)
1126 slice->source = data->source;
1128 slice->source =
self;
1133 int rb_io_buffer_get_bytes(
VALUE self,
void **base,
size_t *size)
1138 if (io_buffer_validate(data)) {
1154 io_buffer_get_bytes_for_writing(
struct rb_io_buffer *data,
void **base,
size_t *size)
1156 if (data->flags & RB_IO_BUFFER_READONLY) {
1157 rb_raise(rb_eIOBufferAccessError,
"Buffer is not writable!");
1160 if (!io_buffer_validate(data)) {
1161 rb_raise(rb_eIOBufferInvalidatedError,
"Buffer is invalid!");
1171 rb_raise(rb_eIOBufferAllocationError,
"The buffer is not allocated!");
1175 rb_io_buffer_get_bytes_for_writing(
VALUE self,
void **base,
size_t *size)
1180 io_buffer_get_bytes_for_writing(data, base, size);
1184 io_buffer_get_bytes_for_reading(
struct rb_io_buffer *data,
const void **base,
size_t *size)
1186 if (!io_buffer_validate(data)) {
1187 rb_raise(rb_eIOBufferInvalidatedError,
"Buffer has been invalidated!");
1197 rb_raise(rb_eIOBufferAllocationError,
"The buffer is not allocated!");
1201 rb_io_buffer_get_bytes_for_reading(
VALUE self,
const void **base,
size_t *size)
1206 io_buffer_get_bytes_for_reading(data, base, size);
1228 rb_io_buffer_transfer(
VALUE self)
1233 if (data->flags & RB_IO_BUFFER_LOCKED) {
1234 rb_raise(rb_eIOBufferLockedError,
"Cannot transfer ownership of locked buffer!");
1241 *transferred = *data;
1242 io_buffer_zero(data);
1248 io_buffer_resize_clear(
struct rb_io_buffer *data,
void* base,
size_t size)
1250 if (size > data->size) {
1251 memset((
unsigned char*)base+data->size, 0, size - data->size);
1256 io_buffer_resize_copy(
struct rb_io_buffer *data,
size_t size)
1260 io_buffer_initialize(&resized, NULL, size, io_flags_for_size(size),
Qnil);
1263 size_t preserve = data->size;
1264 if (preserve > size) preserve = size;
1265 memcpy(resized.base, data->base, preserve);
1267 io_buffer_resize_clear(data, resized.base, size);
1270 io_buffer_free(data);
1275 rb_io_buffer_resize(
VALUE self,
size_t size)
1280 if (data->flags & RB_IO_BUFFER_LOCKED) {
1281 rb_raise(rb_eIOBufferLockedError,
"Cannot resize locked buffer!");
1284 if (data->base == NULL) {
1285 io_buffer_initialize(data, NULL, size, io_flags_for_size(size),
Qnil);
1289 if (data->flags & RB_IO_BUFFER_EXTERNAL) {
1290 rb_raise(rb_eIOBufferAccessError,
"Cannot resize external buffer!");
1293 #ifdef MREMAP_MAYMOVE
1294 if (data->flags & RB_IO_BUFFER_MAPPED) {
1295 void *base = mremap(data->base, data->size, size, MREMAP_MAYMOVE);
1297 if (base == MAP_FAILED) {
1301 io_buffer_resize_clear(data, base, size);
1310 if (data->flags & RB_IO_BUFFER_INTERNAL) {
1311 void *base = realloc(data->base, size);
1317 io_buffer_resize_clear(data, base, size);
1325 io_buffer_resize_copy(data, size);
1350 rb_io_buffer_resize(
self,
NUM2SIZET(size));
1363 rb_io_buffer_compare(
VALUE self,
VALUE other)
1365 const void *ptr1, *ptr2;
1366 size_t size1, size2;
1368 rb_io_buffer_get_bytes_for_reading(
self, &ptr1, &size1);
1369 rb_io_buffer_get_bytes_for_reading(other, &ptr2, &size2);
1371 if (size1 < size2) {
1375 if (size1 > size2) {
1379 return RB_INT2NUM(memcmp(ptr1, ptr2, size1));
1383 io_buffer_validate_type(
size_t size,
size_t offset)
1385 if (offset > size) {
1408 #define ruby_swap8(value) value
1416 ruby_swapf32(
float value)
1418 union swapf32 swap = {.value = value};
1419 swap.integral = ruby_swap32(swap.integral);
1429 ruby_swapf64(
double value)
1431 union swapf64 swap = {.value = value};
1432 swap.integral = ruby_swap64(swap.integral);
1436 #define DECLARE_TYPE(name, type, endian, wrap, unwrap, swap) \
1437 static ID RB_IO_BUFFER_TYPE_##name; \
1440 io_buffer_read_##name(const void* base, size_t size, size_t *offset) \
1442 io_buffer_validate_type(size, *offset + sizeof(type)); \
1444 memcpy(&value, (char*)base + *offset, sizeof(type)); \
1445 if (endian != RB_IO_BUFFER_HOST_ENDIAN) value = swap(value); \
1446 *offset += sizeof(type); \
1447 return wrap(value); \
1451 io_buffer_write_##name(const void* base, size_t size, size_t *offset, VALUE _value) \
1453 io_buffer_validate_type(size, *offset + sizeof(type)); \
1454 type value = unwrap(_value); \
1455 if (endian != RB_IO_BUFFER_HOST_ENDIAN) value = swap(value); \
1456 memcpy((char*)base + *offset, &value, sizeof(type)); \
1457 *offset += sizeof(type); \
1475 DECLARE_TYPE(s64, int64_t, RB_IO_BUFFER_LITTLE_ENDIAN,
RB_LL2NUM,
RB_NUM2LL, ruby_swap64)
1476 DECLARE_TYPE(S64, int64_t, RB_IO_BUFFER_BIG_ENDIAN,
RB_LL2NUM,
RB_NUM2LL, ruby_swap64)
1478 DECLARE_TYPE(f32,
float, RB_IO_BUFFER_LITTLE_ENDIAN,
DBL2NUM,
NUM2DBL, ruby_swapf32)
1479 DECLARE_TYPE(F32,
float, RB_IO_BUFFER_BIG_ENDIAN,
DBL2NUM,
NUM2DBL, ruby_swapf32)
1480 DECLARE_TYPE(f64,
double, RB_IO_BUFFER_LITTLE_ENDIAN,
DBL2NUM,
NUM2DBL, ruby_swapf64)
1481 DECLARE_TYPE(F64,
double, RB_IO_BUFFER_BIG_ENDIAN,
DBL2NUM,
NUM2DBL, ruby_swapf64)
1485 rb_io_buffer_get_value(
const void* base,
size_t size,
ID type,
size_t offset)
1487 #define READ_TYPE(name) if (type == RB_IO_BUFFER_TYPE_##name) return io_buffer_read_##name(base, size, &offset);
1555 rb_io_buffer_get_bytes_for_reading(
self, &base, &size);
1557 return rb_io_buffer_get_value(base, size,
RB_SYM2ID(
type), offset);
1561 rb_io_buffer_set_value(
const void* base,
size_t size,
ID type,
size_t offset,
VALUE value)
1563 #define WRITE_TYPE(name) if (type == RB_IO_BUFFER_TYPE_##name) {io_buffer_write_##name(base, size, &offset, value); return;}
1625 rb_io_buffer_get_bytes_for_writing(
self, &base, &size);
1627 rb_io_buffer_set_value(base, size,
RB_SYM2ID(
type), offset, value);
1633 io_buffer_memcpy(
struct rb_io_buffer *data,
size_t offset,
const void *source_base,
size_t source_offset,
size_t source_size,
size_t length)
1637 io_buffer_get_bytes_for_writing(data, &base, &size);
1639 io_buffer_validate_range(data, offset, length);
1641 if (source_offset + length > source_size) {
1645 memcpy((
unsigned char*)base+offset, (
unsigned char*)source_base+source_offset, length);
1650 io_buffer_copy_from(
struct rb_io_buffer *data,
const void *source_base,
size_t source_size,
int argc,
VALUE *argv)
1654 size_t source_offset;
1667 if (source_offset > source_size) {
1675 if (argc >= 2 && !
RB_NIL_P(argv[1])) {
1679 length = source_size - source_offset;
1682 io_buffer_memcpy(data, offset, source_base, source_offset, source_size, length);
1743 io_buffer_copy(
int argc,
VALUE *argv,
VALUE self)
1745 if (argc < 1 || argc > 4) rb_error_arity(argc, 1, 4);
1750 VALUE source = argv[0];
1751 const void *source_base;
1754 rb_io_buffer_get_bytes_for_reading(source, &source_base, &source_size);
1756 return io_buffer_copy_from(data, source_base, source_size, argc-1, argv+1);
1776 io_buffer_get_string(
int argc,
VALUE *argv,
VALUE self)
1778 if (argc > 3) rb_error_arity(argc, 0, 3);
1785 io_buffer_get_bytes_for_reading(data, &base, &size);
1788 size_t length = size;
1795 if (argc >= 2 && !
RB_NIL_P(argv[1])) {
1798 length = size - offset;
1805 io_buffer_validate_range(data, offset, length);
1807 return rb_enc_str_new((
const char*)base + offset, length, encoding);
1811 io_buffer_set_string(
int argc,
VALUE *argv,
VALUE self)
1813 if (argc < 1 || argc > 4) rb_error_arity(argc, 1, 4);
1823 return io_buffer_copy_from(data, source_base, source_size, argc-1, argv+1);
1827 rb_io_buffer_clear(
VALUE self, uint8_t value,
size_t offset,
size_t length)
1832 rb_io_buffer_get_bytes_for_writing(
self, &base, &size);
1834 if (offset + length > size) {
1838 memset((
char*)base + offset, value, length);
1874 io_buffer_clear(
int argc,
VALUE *argv,
VALUE self)
1876 if (argc > 3) rb_error_arity(argc, 0, 3);
1895 length = data->size - offset;
1898 rb_io_buffer_clear(
self, value, offset, length);
1904 size_t io_buffer_default_size(
size_t page_size) {
1906 const size_t platform_agnostic_default_size = 64*1024;
1909 const char *default_size = getenv(
"RUBY_IO_BUFFER_DEFAULT_SIZE");
1912 int value = atoi(default_size);
1920 if (platform_agnostic_default_size < page_size) {
1924 return platform_agnostic_default_size;
1928 rb_io_buffer_read(
VALUE self,
VALUE io,
size_t length)
1931 if (scheduler !=
Qnil) {
1942 io_buffer_validate_range(data, 0, length);
1948 io_buffer_get_bytes_for_writing(data, &base, &size);
1950 ssize_t result = read(descriptor, base, size);
1958 return rb_io_buffer_read(
self, io,
RB_NUM2SIZE(length));
1962 rb_io_buffer_pread(
VALUE self,
VALUE io,
size_t length, off_t offset)
1965 if (scheduler !=
Qnil) {
1976 io_buffer_validate_range(data, 0, length);
1982 io_buffer_get_bytes_for_writing(data, &base, &size);
1984 #if defined(HAVE_PREAD)
1985 ssize_t result = pread(descriptor, base, size, offset);
1988 off_t current_offset = lseek(descriptor, 0, SEEK_CUR);
1989 if (current_offset == (off_t)-1)
1992 if (lseek(descriptor, offset, SEEK_SET) == (off_t)-1)
1995 ssize_t result = read(descriptor, base, size);
1997 if (lseek(descriptor, current_offset, SEEK_SET) == (off_t)-1)
2011 rb_io_buffer_write(
VALUE self,
VALUE io,
size_t length)
2014 if (scheduler !=
Qnil) {
2025 io_buffer_validate_range(data, 0, length);
2031 io_buffer_get_bytes_for_reading(data, &base, &size);
2033 ssize_t result = write(descriptor, base, length);
2041 return rb_io_buffer_write(
self, io,
RB_NUM2SIZE(length));
2045 rb_io_buffer_pwrite(
VALUE self,
VALUE io,
size_t length, off_t offset)
2048 if (scheduler !=
Qnil) {
2059 io_buffer_validate_range(data, 0, length);
2065 io_buffer_get_bytes_for_reading(data, &base, &size);
2067 #if defined(HAVE_PWRITE)
2068 ssize_t result = pwrite(descriptor, base, length, offset);
2071 off_t current_offset = lseek(descriptor, 0, SEEK_CUR);
2072 if (current_offset == (off_t)-1)
2075 if (lseek(descriptor, offset, SEEK_SET) == (off_t)-1)
2078 ssize_t result = write(descriptor, base, length);
2080 if (lseek(descriptor, current_offset, SEEK_SET) == (off_t)-1)
2177 Init_IO_Buffer(
void)
2190 GetSystemInfo(&info);
2191 RUBY_IO_BUFFER_PAGE_SIZE = info.dwPageSize;
2193 RUBY_IO_BUFFER_PAGE_SIZE = sysconf(_SC_PAGESIZE);
2196 RUBY_IO_BUFFER_DEFAULT_SIZE = io_buffer_default_size(RUBY_IO_BUFFER_PAGE_SIZE);
2251 #define DEFINE_TYPE(name) RB_IO_BUFFER_TYPE_##name = rb_intern_const(#name)
2252 DEFINE_TYPE(U8); DEFINE_TYPE(S8);
2253 DEFINE_TYPE(u16); DEFINE_TYPE(U16); DEFINE_TYPE(s16); DEFINE_TYPE(S16);
2254 DEFINE_TYPE(u32); DEFINE_TYPE(U32); DEFINE_TYPE(s32); DEFINE_TYPE(S32);
2255 DEFINE_TYPE(u64); DEFINE_TYPE(U64); DEFINE_TYPE(s64); DEFINE_TYPE(S64);
2256 DEFINE_TYPE(f32); DEFINE_TYPE(F32); DEFINE_TYPE(f64); DEFINE_TYPE(F64);
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
static bool RB_OBJ_FROZEN(VALUE obj)
Checks if an object is frozen.
void rb_include_module(VALUE klass, VALUE module)
Includes a module to a class.
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a method.
int rb_block_given_p(void)
Determines if the current method is given a block.
#define T_STRING
Old name of RUBY_T_STRING.
#define Qundef
Old name of RUBY_Qundef.
#define CLASS_OF
Old name of rb_class_of.
#define SIZET2NUM
Old name of RB_SIZE2NUM.
#define NUM2UINT
Old name of RB_NUM2UINT.
#define NUM2DBL
Old name of rb_num2dbl.
#define Qnil
Old name of RUBY_Qnil.
#define DBL2NUM
Old name of rb_float_new.
#define NUM2SIZET
Old name of RB_NUM2SIZE.
void rb_category_warn(rb_warning_category_t category, const char *fmt,...)
Identical to rb_category_warning(), except it reports always regardless of runtime -W flag.
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
void rb_sys_fail(const char *mesg)
Converts a C errno into a Ruby exception, then raises it.
VALUE rb_eRuntimeError
RuntimeError exception.
VALUE rb_eArgError
ArgumentError exception.
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
@ RB_WARN_CATEGORY_EXPERIMENTAL
Warning is for experimental features.
static VALUE rb_class_of(VALUE obj)
Object to class mapping function.
VALUE rb_mComparable
Comparable module.
rb_encoding * rb_find_encoding(VALUE obj)
Identical to rb_to_encoding_index(), except the return type.
rb_encoding * rb_ascii8bit_encoding(void)
Queries the encoding that represents ASCII-8BIT a.k.a.
VALUE rb_enc_str_new(const char *ptr, long len, rb_encoding *enc)
Identical to rb_enc_str_new(), except it additionally takes an encoding.
off_t rb_file_size(VALUE file)
Queries the file size of the given file.
void rb_gc_mark(VALUE obj)
Marks an object.
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
VALUE rb_str_cat2(VALUE, const char *)
Just another name of rb_str_cat_cstr.
VALUE rb_str_locktmp(VALUE str)
Obtains a "temporary lock" of the string.
VALUE rb_str_unlocktmp(VALUE str)
Releases a lock formerly obtained by rb_str_locktmp().
VALUE rb_str_new_cstr(const char *ptr)
Identical to rb_str_new(), except it assumes the passed pointer is a pointer to a C string.
VALUE rb_str_buf_new(long capa)
Allocates a "string buffer".
VALUE rb_class_name(VALUE obj)
Queries the name of the given object's class.
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
#define RB_SYM2ID
Just another name of rb_sym2id.
void rb_define_const(VALUE klass, const char *name, VALUE val)
Defines a Ruby level constant under a namespace.
int rb_io_descriptor(VALUE io)
Returns an integer representing the numeric file descriptor for io.
#define RB_NUM2INT
Just another name of rb_num2int_inline.
#define RB_UINT2NUM
Just another name of rb_uint2num_inline.
#define RB_INT2NUM
Just another name of rb_int2num_inline.
static unsigned int RB_NUM2UINT(VALUE x)
Converts an instance of rb_cNumeric into C's unsigned int.
VALUE rb_str_catf(VALUE dst, const char *fmt,...)
Identical to rb_sprintf(), except it renders the output to the specified object rather than creating ...
#define RB_LL2NUM
Just another name of rb_ll2num_inline.
#define RB_ULL2NUM
Just another name of rb_ull2num_inline.
#define RB_NUM2ULL
Just another name of rb_num2ull_inline.
#define RB_NUM2LL
Just another name of rb_num2ll_inline.
VALUE rb_yield(VALUE val)
Yields the block.
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define OFFT2NUM
Converts a C's off_t into an instance of rb_cInteger.
#define NUM2OFFT
Converts an instance of rb_cNumeric into C's off_t.
#define StringValue(v)
Ensures that the parameter object is a String.
static char * RSTRING_PTR(VALUE str)
Queries the contents pointer of the string.
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Convenient macro to obtain the contents and length at once.
static long RSTRING_LEN(VALUE str)
Queries the length of the string.
VALUE rb_str_to_str(VALUE obj)
Identical to rb_check_string_type(), except it raises exceptions in case of conversion failures.
#define TypedData_Get_Struct(obj, type, data_type, sval)
Obtains a C struct from inside of a wrapper Ruby object.
#define TypedData_Make_Struct(klass, type, data_type, sval)
Identical to TypedData_Wrap_Struct, except it allocates a new data region internally instead of takin...
VALUE rb_fiber_scheduler_current(void)
Identical to rb_fiber_scheduler_get(), except it also returns RUBY_Qnil in case of a blocking fiber.
static VALUE rb_fiber_scheduler_io_result(ssize_t result, int error)
Wrap a ssize_t and int errno into a single VALUE.
VALUE rb_fiber_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t length)
Nonblocking read from the passed IO.
VALUE rb_fiber_scheduler_io_pread(VALUE scheduler, VALUE io, VALUE buffer, size_t length, off_t offset)
Nonblocking read from the passed IO at the specified offset.
VALUE rb_fiber_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t length)
Nonblocking write to the passed IO.
VALUE rb_fiber_scheduler_io_pwrite(VALUE scheduler, VALUE io, VALUE buffer, size_t length, off_t offset)
Nonblocking write to the passed IO at the specified offset.
#define RB_NUM2SIZE
Converts an instance of rb_cInteger into C's size_t.
static bool RB_NIL_P(VALUE obj)
Checks if the given object is nil.
This is the struct that holds necessary info for a struct.
const char * wrap_struct_name
Name of structs of this kind.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
uintptr_t VALUE
Type that represents a Ruby object.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.