Ruby 4.1.0dev (2026-03-05 revision 8a87cebd1874f8f9f68af8928191ee3f0d97bb28)
struct.h
1#ifndef INTERNAL_STRUCT_H /*-*-C-*-vi:se ft=c:*/
2#define INTERNAL_STRUCT_H
11#include "ruby/internal/stdbool.h" /* for bool */
12#include "ruby/ruby.h" /* for struct RBasic */
13
14/* Flags of RStruct
15 *
16 * 1-7: RSTRUCT_EMBED_LEN
17 * If non-zero, the struct is embedded (its contents follow the
18 * header, rather than being on a separately allocated buffer) and
19 * these bits are the length of the Struct.
20 * 8: RSTRUCT_GEN_FIELDS
21 * The struct is embedded and has no space left to store the
22 * IMEMO/fields reference. Any ivar this struct may have will be in
23 * the generic_fields_tbl. This flag doesn't imply the struct has
24 * ivars.
25 */
26enum {
27 RSTRUCT_EMBED_LEN_MASK = RUBY_FL_USER7 | RUBY_FL_USER6 | RUBY_FL_USER5 | RUBY_FL_USER4 |
29 RSTRUCT_EMBED_LEN_SHIFT = (RUBY_FL_USHIFT+1),
30 RSTRUCT_GEN_FIELDS = RUBY_FL_USER8,
31};
32
33struct RStruct {
34 struct RBasic basic;
35 union {
36 struct {
37 long len;
38 const VALUE *ptr;
39 VALUE fields_obj;
40 } heap;
41 /* This is a length 1 array because:
42 * 1. GCC has a bug that does not optimize C flexible array members
43 * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452)
44 * 2. Zero length arrays are not supported by all compilers
45 */
46 const VALUE ary[1];
47 } as;
48};
49
50#define RSTRUCT(obj) ((struct RStruct *)(obj))
51
52/* struct.c */
53VALUE rb_struct_init_copy(VALUE copy, VALUE s);
54VALUE rb_struct_lookup(VALUE s, VALUE idx);
55VALUE rb_struct_s_keyword_init(VALUE klass);
56static inline long RSTRUCT_EMBED_LEN(VALUE st);
57static inline long RSTRUCT_LEN_RAW(VALUE st);
58static inline int RSTRUCT_LENINT(VALUE st);
59static inline const VALUE *RSTRUCT_CONST_PTR(VALUE st);
60static inline void RSTRUCT_SET_RAW(VALUE st, long k, VALUE v);
61static inline VALUE RSTRUCT_GET_RAW(VALUE st, long k);
62
63static inline long
64RSTRUCT_EMBED_LEN(VALUE st)
65{
66 long ret = FL_TEST_RAW(st, RSTRUCT_EMBED_LEN_MASK);
67 ret >>= RSTRUCT_EMBED_LEN_SHIFT;
68 return ret;
69}
70
71static inline long
72RSTRUCT_LEN_RAW(VALUE st)
73{
74 if (FL_TEST_RAW(st, RSTRUCT_EMBED_LEN_MASK)) {
75 return RSTRUCT_EMBED_LEN(st);
76 }
77 else {
78 return RSTRUCT(st)->as.heap.len;
79 }
80}
81
82static inline int
83RSTRUCT_LENINT(VALUE st)
84{
85 return rb_long2int(RSTRUCT_LEN_RAW(st));
86}
87
88static inline const VALUE *
89RSTRUCT_CONST_PTR(VALUE st)
90{
91 const struct RStruct *p = RSTRUCT(st);
92
93 if (FL_TEST_RAW(st, RSTRUCT_EMBED_LEN_MASK)) {
94 return p->as.ary;
95 }
96 else {
97 return p->as.heap.ptr;
98 }
99}
100
101static inline void
102RSTRUCT_SET_RAW(VALUE st, long k, VALUE v)
103{
104 RB_OBJ_WRITE(st, &RSTRUCT_CONST_PTR(st)[k], v);
105}
106
107static inline VALUE
108RSTRUCT_GET_RAW(VALUE st, long k)
109{
110 return RSTRUCT_CONST_PTR(st)[k];
111}
112
113static inline VALUE
114RSTRUCT_FIELDS_OBJ(VALUE st)
115{
116 const long embed_len = RSTRUCT_EMBED_LEN(st);
117 VALUE fields_obj;
118 if (embed_len) {
119 RUBY_ASSERT(!FL_TEST_RAW(st, RSTRUCT_GEN_FIELDS));
120 fields_obj = RSTRUCT_GET_RAW(st, embed_len);
121 }
122 else {
123 fields_obj = RSTRUCT(st)->as.heap.fields_obj;
124 }
125 return fields_obj;
126}
127
128static inline void
129RSTRUCT_SET_FIELDS_OBJ(VALUE st, VALUE fields_obj)
130{
131 const long embed_len = RSTRUCT_EMBED_LEN(st);
132 if (embed_len) {
133 RUBY_ASSERT(!FL_TEST_RAW(st, RSTRUCT_GEN_FIELDS));
134 RSTRUCT_SET_RAW(st, embed_len, fields_obj);
135 }
136 else {
137 RB_OBJ_WRITE(st, &RSTRUCT(st)->as.heap.fields_obj, fields_obj);
138 }
139}
140#endif /* INTERNAL_STRUCT_H */
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
Definition assert.h:219
@ RUBY_FL_USHIFT
Number of bits in ruby_fl_type that are not open to users.
Definition fl_type.h:146
@ RUBY_FL_USER8
User-defined flag.
Definition fl_type.h:290
@ RUBY_FL_USER5
User-defined flag.
Definition fl_type.h:287
@ RUBY_FL_USER3
User-defined flag.
Definition fl_type.h:285
@ RUBY_FL_USER7
User-defined flag.
Definition fl_type.h:289
@ RUBY_FL_USER6
User-defined flag.
Definition fl_type.h:288
@ RUBY_FL_USER2
User-defined flag.
Definition fl_type.h:284
@ RUBY_FL_USER4
User-defined flag.
Definition fl_type.h:286
@ RUBY_FL_USER1
User-defined flag.
Definition fl_type.h:283
#define FL_TEST_RAW
Old name of RB_FL_TEST_RAW.
Definition fl_type.h:128
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
Definition gc.h:603
int len
Length of the buffer.
Definition io.h:8
#define rb_long2int
Just another name of rb_long2int_inline.
Definition long.h:62
C99 shim for <stdbool.h>
Ruby object's base components.
Definition rbasic.h:69
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40