9#include "internal/bits.h"
10#include "internal/hash.h"
11#include "internal/proc.h"
12#include "internal/sanitizers.h"
13#include "internal/set_table.h"
14#include "internal/symbol.h"
15#include "internal/variable.h"
16#include "ruby_assert.h"
29#include "internal/gc.h"
35 union {
double d; st_index_t i;} u;
40static const uint64_t prime1 = ((uint64_t)0x2e0bb864 << 32) | 0xe9ea7df5;
41static const uint32_t prime2 = 0x830fcab9;
44mult_and_mix(uint64_t m1, uint64_t m2)
46#if defined HAVE_UINT128_T
47 uint128_t r = (uint128_t) m1 * (uint128_t) m2;
48 return (uint64_t) (r >> 64) ^ (uint64_t) r;
50 uint64_t hm1 = m1 >> 32, hm2 = m2 >> 32;
51 uint64_t lm1 = m1, lm2 = m2;
52 uint64_t v64_128 = hm1 * hm2;
53 uint64_t v32_96 = hm1 * lm2 + lm1 * hm2;
54 uint64_t v1_32 = lm1 * lm2;
56 return (v64_128 + (v32_96 >> 32)) ^ ((v32_96 << 32) + v1_32);
61key64_hash(uint64_t key, uint32_t seed)
63 return mult_and_mix(key + seed, prime1);
67#define set_index_hash(index) key64_hash(rb_hash_start(index), prime2)
70set_ident_hash(st_data_t n)
79 n ^= dbl_to_index(rb_float_value(n));
83 return (st_index_t)set_index_hash((st_index_t)n);
99static ID id_each_entry;
102static ID id_set_iter_lev;
104#define RSET_INITIALIZED FL_USER1
105#define RSET_LEV_MASK (FL_USER13 | FL_USER14 | FL_USER15 | \
106 FL_USER16 | FL_USER17 | FL_USER18 | FL_USER19)
107#define RSET_LEV_SHIFT (FL_USHIFT + 13)
108#define RSET_LEV_MAX 127
110#define SET_ASSERT(expr) RUBY_ASSERT_MESG_WHEN(SET_DEBUG, expr, #expr)
112#define RSET_SIZE(set) set_table_size(RSET_TABLE(set))
113#define RSET_EMPTY(set) (RSET_SIZE(set) == 0)
114#define RSET_SIZE_NUM(set) SIZET2NUM(RSET_SIZE(set))
115#define RSET_IS_MEMBER(sobj, item) set_lookup(RSET_TABLE(set), (st_data_t)(item))
116#define RSET_COMPARE_BY_IDENTITY(set) (RSET_TABLE(set)->type == &identhash)
123mark_key(st_data_t key, st_data_t data)
125 rb_gc_mark_movable((
VALUE)key);
134 if (sobj->table.entries) set_foreach(&sobj->table, mark_key, 0);
140 free((&sobj->table)->bins);
141 free((&sobj->table)->entries);
148 set_free_embedded(sobj);
149 memset(&sobj->table, 0,
sizeof(sobj->table));
153set_size(
const void *ptr)
157 return (
unsigned long)set_memsize(&sobj->table) -
sizeof(sobj->table);
161set_foreach_replace(st_data_t key, st_data_t argp,
int error)
163 if (rb_gc_location((
VALUE)key) != (
VALUE)key) {
171set_replace_ref(st_data_t *key, st_data_t argp,
int existing)
173 if (rb_gc_location((
VALUE)*key) != (
VALUE)*key) {
174 *key = rb_gc_location((
VALUE)*key);
181set_compact(
void *ptr)
184 set_compact_table(&sobj->table);
185 set_foreach_with_replace(&sobj->table, set_foreach_replace, set_replace_ref, 0);
194 .dcompact = set_compact,
196 .flags = RUBY_TYPED_EMBEDDABLE | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE
208iter_lev_in_ivar(
VALUE set)
213 SET_ASSERT(lev >= 0);
214 return (
unsigned long)lev;
220iter_lev_in_ivar_set(
VALUE set,
unsigned long lev)
222 SET_ASSERT(lev >= RSET_LEV_MAX);
224 rb_ivar_set_internal(set, id_set_iter_lev,
LONG2FIX((
long)lev));
227static inline unsigned long
228iter_lev_in_flags(
VALUE set)
230 return (
unsigned long)((
RBASIC(set)->flags >> RSET_LEV_SHIFT) & RSET_LEV_MAX);
234iter_lev_in_flags_set(
VALUE set,
unsigned long lev)
236 SET_ASSERT(lev <= RSET_LEV_MAX);
237 RBASIC(set)->flags = ((
RBASIC(set)->flags & ~RSET_LEV_MASK) | ((
VALUE)lev << RSET_LEV_SHIFT));
241set_iterating_p(
VALUE set)
243 return iter_lev_in_flags(set) > 0;
247set_iter_lev_inc(
VALUE set)
249 unsigned long lev = iter_lev_in_flags(set);
250 if (lev == RSET_LEV_MAX) {
251 lev = iter_lev_in_ivar(set) + 1;
258 iter_lev_in_flags_set(set, lev);
259 if (lev < RSET_LEV_MAX)
return;
261 iter_lev_in_ivar_set(set, lev);
265set_iter_lev_dec(
VALUE set)
267 unsigned long lev = iter_lev_in_flags(set);
268 if (lev == RSET_LEV_MAX) {
269 lev = iter_lev_in_ivar(set);
270 if (lev > RSET_LEV_MAX) {
271 iter_lev_in_ivar_set(set, lev-1);
274 rb_attr_delete(set, id_set_iter_lev);
279 iter_lev_in_flags_set(set, lev - 1);
283set_foreach_ensure(
VALUE set)
285 set_iter_lev_dec(set);
293 set_foreach_func *func;
298set_iter_status_check(
int status)
300 if (status == ST_CONTINUE) {
308set_foreach_iter(st_data_t key, st_data_t argp,
int error)
312 if (error)
return ST_STOP;
315 int status = (*arg->func)((
VALUE)key, arg->arg);
317 if (RSET_TABLE(arg->set) != tbl) {
321 return set_iter_status_check(status);
325set_foreach_call(
VALUE arg)
329 ret = set_foreach_check(RSET_TABLE(set), set_foreach_iter,
330 (st_data_t)arg, (st_data_t)
Qundef);
338set_iter(
VALUE set, set_foreach_func *func,
VALUE farg)
348 set_foreach_call((
VALUE)&arg);
351 set_iter_lev_inc(set);
352 rb_ensure(set_foreach_call, (
VALUE)&arg, set_foreach_ensure, set);
356NORETURN(
static void no_new_item(
void));
360 rb_raise(
rb_eRuntimeError,
"can't add a new item into set during iteration");
364set_compact_after_delete(
VALUE set)
366 if (!set_iterating_p(set)) {
367 set_compact_table(RSET_TABLE(set));
375 key = rb_hash_key_str(key);
376 if (key_addr) *key_addr = key;
378 int ret = set_insert(tab, (st_data_t)key);
386 return set_table_insert_wb(RSET_TABLE(set), set, key, key_addr);
390set_alloc_with_size(
VALUE klass, st_index_t size)
396 set_init_table_with_size(&sobj->table, &objhash, size);
403set_s_alloc(
VALUE klass)
405 return set_alloc_with_size(klass, 0);
409set_s_create(
int argc,
VALUE *argv,
VALUE klass)
411 VALUE set = set_alloc_with_size(klass, argc);
415 for (i=0; i < argc; i++) {
416 set_table_insert_wb(table, set, argv[i], NULL);
426 rb_raise(rb_eArgError,
"value must be a set");
431enum_method_id(
VALUE other)
434 return id_each_entry;
440 rb_raise(rb_eArgError,
"value must be enumerable");
447 return RSET_SIZE_NUM(set);
454 set_insert_wb(set, element, &element);
462 set_insert_wb(set, element, &element);
485set_i_initialize(
int argc,
VALUE *argv,
VALUE set)
487 if (
RBASIC(set)->flags & RSET_INITIALIZED) {
490 RBASIC(set)->flags |= RSET_INITIALIZED;
495 if (argc > 0 && (other = argv[0]) !=
Qnil) {
503 for(;
len > 0;
len--, ptr++) {
505 if (block_given) key =
rb_yield(key);
506 set_table_insert_wb(into, set, key, NULL);
513 rb_block_given_p() ? set_initialize_with_block : set_initialize_without_block,
524 if (set == other)
return set;
526 if (set_iterating_p(set)) {
533 set_free_embedded(sobj);
534 set_copy(&sobj->table, RSET_TABLE(other));
540set_inspect_i(st_data_t key, st_data_t arg)
543 if (RSTRING_LEN(str) > 8) {
558 set_iter(set, set_inspect_i, str);
580set_i_inspect(
VALUE set)
586set_to_a_i(st_data_t key, st_data_t arg)
604 st_index_t size = RSET_SIZE(set);
605 VALUE ary = rb_ary_new_capa(size);
607 if (size == 0)
return ary;
609 if (ST_DATA_COMPATIBLE_P(
VALUE)) {
611 size = set_keys(RSET_TABLE(set), ptr, size);
613 rb_gc_writebarrier_remember(ary);
614 rb_ary_set_len(ary, size);
617 set_iter(set, set_to_a_i, (st_data_t)ary);
665 return rb_ary_join(set_i_to_a(set), argc == 0 ?
Qnil : argv[0]);
682 rb_check_frozen(set);
683 if (set_iterating_p(set)) {
684 if (!set_lookup(RSET_TABLE(set), (st_data_t)item)) {
689 set_insert_wb(set, item, NULL);
708 rb_check_frozen(set);
709 if (set_iterating_p(set)) {
710 if (!set_lookup(RSET_TABLE(set), (st_data_t)item)) {
716 return set_insert_wb(set, item, NULL) ?
Qnil : set;
730 rb_check_frozen(set);
731 if (set_delete(RSET_TABLE(set), (st_data_t *)&item)) {
732 set_compact_after_delete(set);
747 rb_check_frozen(set);
748 if (set_delete(RSET_TABLE(set), (st_data_t *)&item)) {
749 set_compact_after_delete(set);
756set_delete_if_i(st_data_t key, st_data_t dummy)
770set_i_delete_if(
VALUE set)
773 rb_check_frozen(set);
774 set_iter(set, set_delete_if_i, 0);
775 set_compact_after_delete(set);
788set_i_reject(
VALUE set)
791 rb_check_frozen(set);
794 size_t n = set_table_size(table);
795 set_iter(set, set_delete_if_i, 0);
797 if (n == set_table_size(table))
return Qnil;
799 set_compact_after_delete(set);
804set_classify_i(st_data_t key, st_data_t tmp)
807 VALUE hash = args[0];
809 VALUE set = rb_hash_lookup2(hash, hash_key,
Qundef);
811 set = set_s_alloc(args[1]);
812 rb_hash_aset(hash, hash_key, set);
838set_i_classify(
VALUE set)
842 args[0] = rb_hash_new();
844 set_iter(set, set_classify_i, (st_data_t)args);
863 if (args->nj > args->ni) {
864 VALUE i = args->current_item;
866 VALUE hash = args->hash;
867 if (args->current_set ==
Qnil) {
868 VALUE set = rb_hash_aref(hash, j);
870 VALUE both[2] = {i, j};
871 set = set_s_create(2, both, args->set_class);
872 rb_hash_aset(hash, i, set);
873 rb_hash_aset(hash, j, set);
874 set_i_add(args->final_set, set);
878 rb_hash_aset(hash, i, set);
880 args->current_set = set;
883 set_i_add(args->current_set, j);
884 rb_hash_aset(hash, j, args->current_set);
896 VALUE hash = args->hash;
897 args->current_set = rb_hash_aref(hash, i);
898 args->current_item = i;
900 rb_block_call(args->self, id_each, 0, 0, set_divide_block0, arg);
901 if (args->current_set ==
Qnil) {
902 VALUE set = set_s_create(1, &i, args->set_class);
903 rb_hash_aset(hash, i, set);
904 set_i_add(args->final_set, set);
910static void set_merge_enum_into(
VALUE set,
VALUE arg);
936set_i_divide(
VALUE set)
940 if (rb_block_arity() == 2) {
941 VALUE final_set = set_s_create(0, 0, rb_cSet);
945 .final_set = final_set,
946 .hash = rb_hash_new(),
956 VALUE values = rb_hash_values(set_i_classify(set));
957 set = set_alloc_with_size(rb_cSet,
RARRAY_LEN(values));
958 set_merge_enum_into(set, values);
963set_clear_i(st_data_t key, st_data_t dummy)
979set_i_clear(
VALUE set)
981 rb_check_frozen(set);
982 if (RSET_SIZE(set) == 0)
return set;
983 if (set_iterating_p(set)) {
984 set_iter(set, set_clear_i, 0);
987 set_clear(RSET_TABLE(set));
988 set_compact_after_delete(set);
1000set_intersection_i(st_data_t key, st_data_t tmp)
1003 if (set_lookup(data->other, key)) {
1004 set_table_insert_wb(data->into, data->set, key, NULL);
1013 set_intersection_i((st_data_t)i, (st_data_t)data);
1032 set_table *ntable = RSET_TABLE(new_set);
1036 if (set_table_size(stable) >= set_table_size(otable)) {
1047 set_iter(set, set_intersection_i, (st_data_t)&data);
1055 rb_block_call(other, enum_method_id(other), 0, 0, set_intersection_block, (
VALUE)&data);
1088 return RBOOL(RSET_IS_MEMBER(set, item));
1097set_merge_i(st_data_t key, st_data_t data)
1100 set_table_insert_wb(args->into, args->set, key, NULL);
1107 VALUE element = key;
1108 set_insert_wb(set, element, &element);
1118 .into = RSET_TABLE(set)
1120 set_iter(arg, set_merge_i, (st_data_t)&args);
1127 for(;
len > 0;
len--, ptr++) {
1128 set_table_insert_wb(into, set, *ptr, NULL);
1149 rb_raise(rb_eArgError,
"no keywords accepted");
1151 rb_check_frozen(set);
1155 for (i=0; i < argc; i++) {
1156 set_merge_enum_into(set, argv[i]);
1165 rb_check_frozen(set);
1171 size_t size = set_table_size(old);
1173 set_table *
new = set_init_table_with_size(NULL,
type, size);
1178 set_iter(set, set_merge_i, (st_data_t)&args);
1179 set_free_embedded(sobj);
1180 memcpy(&sobj->table,
new,
sizeof(*
new));
1184 sobj->table.type =
type;
1197set_i_compare_by_identity(
VALUE set)
1199 if (RSET_COMPARE_BY_IDENTITY(set))
return set;
1201 if (set_iterating_p(set)) {
1205 return set_reset_table_with_type(set, &identhash);
1216set_i_compare_by_identity_p(
VALUE set)
1218 return RBOOL(RSET_COMPARE_BY_IDENTITY(set));
1228set_i_size(
VALUE set)
1230 return RSET_SIZE_NUM(set);
1240set_i_empty(
VALUE set)
1242 return RBOOL(RSET_EMPTY(set));
1246set_xor_i(st_data_t key, st_data_t data)
1251 if (set_table_insert_wb(table, set, element, &element)) {
1252 set_delete(table, &element);
1277 set_merge_enum_into(new_set, other);
1279 set_iter(set, set_xor_i, (st_data_t)new_set);
1297 set_merge_enum_into(set, other);
1302set_remove_i(st_data_t key, st_data_t from)
1304 set_delete((
struct set_table *)from, (st_data_t *)&key);
1311 rb_check_frozen(set);
1312 set_delete(RSET_TABLE(set), (st_data_t *)&key);
1320 set_iter(arg, set_remove_i, (st_data_t)RSET_TABLE(set));
1337 rb_check_frozen(set);
1338 set_remove_enum_from(set, other);
1355 return set_i_subtract(
rb_obj_dup(set), other);
1359set_each_i(st_data_t key, st_data_t dummy)
1375set_i_each(
VALUE set)
1378 set_iter(set, set_each_i, 0);
1383set_collect_i(st_data_t key, st_data_t data)
1398set_i_collect(
VALUE set)
1401 rb_check_frozen(set);
1404 set_iter(set, set_collect_i, (st_data_t)new_set);
1405 set_i_initialize_copy(set, new_set);
1411set_keep_if_i(st_data_t key, st_data_t into)
1428set_i_keep_if(
VALUE set)
1431 rb_check_frozen(set);
1433 set_iter(set, set_keep_if_i, (st_data_t)RSET_TABLE(set));
1447set_i_select(
VALUE set)
1450 rb_check_frozen(set);
1453 size_t n = set_table_size(table);
1454 set_iter(set, set_keep_if_i, (st_data_t)table);
1456 return (n == set_table_size(table)) ?
Qnil : set;
1473 rb_check_frozen(set);
1476 set_i_initialize_copy(set, other);
1479 if (set_iterating_p(set)) {
1484 enum_method_id(other);
1486 set_clear(RSET_TABLE(set));
1487 set_merge_enum_into(set, other);
1501set_i_reset(
VALUE set)
1503 if (set_iterating_p(set)) {
1507 return set_reset_table_with_type(set, RSET_TABLE(set)->
type);
1513set_flatten_merge_i(st_data_t item, st_data_t arg)
1516 VALUE set = args[0];
1518 VALUE e_id = rb_obj_id(item);
1519 VALUE hash = args[2];
1520 switch(rb_hash_aref(hash, e_id)) {
1524 rb_raise(rb_eArgError,
"tried to flatten recursive Set");
1529 rb_hash_aset(hash, e_id,
Qtrue);
1530 set_flatten_merge(set, item, hash);
1531 rb_hash_aset(hash, e_id,
Qfalse);
1534 set_i_add(set, item);
1542 VALUE args[3] = {set, from, hash};
1543 set_iter(from, set_flatten_merge_i, (st_data_t)args);
1554set_i_flatten(
VALUE set)
1557 set_flatten_merge(new_set, set, rb_hash_new());
1562set_contains_set_i(st_data_t item, st_data_t arg)
1565 *(
bool *)arg =
true;
1579set_i_flatten_bang(
VALUE set)
1581 bool contains_set =
false;
1582 set_iter(set, set_contains_set_i, (st_data_t)&contains_set);
1583 if (!contains_set)
return Qnil;
1584 rb_check_frozen(set);
1585 return set_i_replace(set, set_i_flatten(set));
1594set_le_i(st_data_t key, st_data_t arg)
1597 if (set_lookup(data->table, key))
return ST_CONTINUE;
1606 .table = RSET_TABLE(other),
1609 set_iter(set, set_le_i, (st_data_t)&data);
1623 if (RSET_SIZE(set) >= RSET_SIZE(other))
return Qfalse;
1624 return set_le(set, other);
1637 if (RSET_SIZE(set) > RSET_SIZE(other))
return Qfalse;
1638 return set_le(set, other);
1651 if (RSET_SIZE(set) <= RSET_SIZE(other))
return Qfalse;
1652 return set_le(other, set);
1665 if (RSET_SIZE(set) < RSET_SIZE(other))
return Qfalse;
1666 return set_le(other, set);
1670set_intersect_i(st_data_t key, st_data_t arg)
1673 if (set_lookup((
set_table *)args[0], key)) {
1696 size_t set_size = RSET_SIZE(set);
1697 size_t other_size = RSET_SIZE(other);
1702 if (set_size < other_size) {
1704 args[0] = (
VALUE)RSET_TABLE(other);
1708 args[0] = (
VALUE)RSET_TABLE(set);
1710 set_iter(iter_arg, set_intersect_i, (st_data_t)args);
1717 rb_raise(rb_eArgError,
"value must be enumerable");
1736 return RBOOL(!
RTEST(set_i_intersect(set, other)));
1751 size_t set_size = RSET_SIZE(set);
1752 size_t other_size = RSET_SIZE(other);
1754 if (set_size < other_size) {
1755 if (set_le(set, other) ==
Qtrue) {
1759 else if (set_size > other_size) {
1760 if (set_le(other, set) ==
Qtrue) {
1764 else if (set_le(set, other) ==
Qtrue) {
1778set_eql_i(st_data_t item, st_data_t arg)
1782 if (!set_lookup(RSET_TABLE(data->set), item)) {
1790set_recursive_eql(
VALUE set,
VALUE dt,
int recur)
1792 if (recur)
return Qtrue;
1794 data->result =
Qtrue;
1795 set_iter(set, set_eql_i, dt);
1796 return data->result;
1809 if (set == other)
return Qtrue;
1813 size_t ssize = set_table_size(stable);
1814 size_t osize = set_table_size(otable);
1816 if (ssize != osize)
return Qfalse;
1817 if (ssize == 0 && osize == 0)
return Qtrue;
1818 if (stable->type != otable->type)
return Qfalse;
1826set_hash_i(st_data_t item, st_data_t(arg))
1828 st_index_t *hval = (st_index_t *)arg;
1829 st_index_t ival = rb_hash(item);
1830 *hval ^= rb_st_hash(&ival,
sizeof(st_index_t), 0);
1841set_i_hash(
VALUE set)
1843 st_index_t size = RSET_SIZE(set);
1844 st_index_t hval = rb_st_hash_start(size);
1847 set_iter(set, set_hash_i, (
VALUE)&hval);
1849 hval = rb_st_hash_end(hval);
2071 id_set_iter_lev = rb_make_internal_id();
2097 rb_define_method(rb_cSet,
"compare_by_identity", set_i_compare_by_identity, 0);
2098 rb_define_method(rb_cSet,
"compare_by_identity?", set_i_compare_by_identity_p, 0);
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#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(const char *name, VALUE super)
Defines a top-level class.
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
int rb_keyword_given_p(void)
Determines if the current method is given a keyword argument.
int rb_block_given_p(void)
Determines if the current method is given a block.
#define rb_str_buf_cat2
Old name of rb_usascii_str_new_cstr.
#define Qundef
Old name of RUBY_Qundef.
#define rb_str_buf_new2
Old name of rb_str_buf_new_cstr.
#define LONG2FIX
Old name of RB_INT2FIX.
#define rb_usascii_str_new2
Old name of rb_usascii_str_new_cstr.
#define FLONUM_P
Old name of RB_FLONUM_P.
#define Qtrue
Old name of RUBY_Qtrue.
#define ST2FIX
Old name of RB_ST2FIX.
#define INT2NUM
Old name of RB_INT2NUM.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
#define T_ARRAY
Old name of RUBY_T_ARRAY.
#define POSFIXABLE
Old name of RB_POSFIXABLE.
#define FIXNUM_P
Old name of RB_FIXNUM_P.
VALUE rb_eRuntimeError
RuntimeError exception.
VALUE rb_mEnumerable
Enumerable module.
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
VALUE rb_obj_dup(VALUE obj)
Duplicates the given object.
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
VALUE rb_obj_is_instance_of(VALUE obj, VALUE klass)
Queries if the given object is a direct instance of the given class.
VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass)
Queries if the given object is an instance (of possibly descendants) of the given class.
VALUE rb_cString
String class.
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
VALUE rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv_public(), except you can pass the passed block.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
This roughly resembles return enum_for(__callee__) unless block_given?.
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
void rb_provide(const char *feature)
Declares that the given feature is already provided by someone else.
#define rb_hash_uint(h, i)
Just another name of st_hash_uint.
VALUE rb_str_buf_append(VALUE dst, VALUE src)
Identical to rb_str_cat_cstr(), except it takes Ruby's string instead of C's.
VALUE rb_str_buf_cat_ascii(VALUE dst, const char *src)
Identical to rb_str_cat_cstr(), except it additionally assumes the source string be a NUL terminated ...
VALUE rb_exec_recursive(VALUE(*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h)
"Recursion" API entry point.
VALUE rb_exec_recursive_paired(VALUE(*f)(VALUE g, VALUE h, int r), VALUE g, VALUE p, VALUE h)
Identical to rb_exec_recursive(), except it checks for the recursion on the ordered pair of { g,...
VALUE rb_ivar_get(VALUE obj, ID name)
Identical to rb_iv_get(), except it accepts the name as an ID instead of a C string.
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
int len
Length of the buffer.
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Shim for block function parameters.
VALUE rb_yield_values(int n,...)
Identical to rb_yield(), except it takes variadic number of parameters and pass them to the block.
VALUE rb_yield(VALUE val)
Yields the block.
VALUE rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y)
Call a method with a block.
VALUE type(ANYARGS)
ANYARGS-ed function type.
VALUE rb_ensure(type *q, VALUE w, type *e, VALUE r)
An equivalent of ensure clause.
#define RARRAY_LEN
Just another name of rb_array_len.
#define RARRAY_PTR_USE(ary, ptr_name, expr)
Declares a section of code where raw pointers are used.
#define RBASIC(obj)
Convenient casting macro.
#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...
#define RTEST
This is an old name of RB_TEST.
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.