Ruby 4.1.0dev (2026-08-15 revision d1c079751b80352d347452c8d134ffb177838adb)
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 */
21enum {
22 RSTRUCT_EMBED_LEN_MASK = RUBY_FL_USER7 | RUBY_FL_USER6 | RUBY_FL_USER5 | RUBY_FL_USER4 |
24 RSTRUCT_EMBED_LEN_SHIFT = (RUBY_FL_USHIFT+1),
25};
26
27struct RStruct {
28 struct RBasic basic;
29 VALUE fields_obj;
30 union {
31 struct {
32 long len;
33 const VALUE *ptr;
34 } heap;
35 /* This is a length 1 array because:
36 * 1. GCC has a bug that does not optimize C flexible array members
37 * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452)
38 * 2. Zero length arrays are not supported by all compilers
39 */
40 const VALUE ary[1];
41 } as;
42};
43
44#define RSTRUCT(obj) ((struct RStruct *)(obj))
45
46/* struct.c */
47VALUE rb_struct_init_copy(VALUE copy, VALUE s);
48VALUE rb_struct_lookup(VALUE s, VALUE idx);
49VALUE rb_struct_s_keyword_init(VALUE klass);
50void rb_struct_define_aref_method(VALUE nstr, ID name, unsigned int off);
51
52static inline long RSTRUCT_EMBED_LEN(VALUE st);
53static inline long RSTRUCT_LEN_RAW(VALUE st);
54static inline int RSTRUCT_LENINT(VALUE st);
55static inline const VALUE *RSTRUCT_CONST_PTR(VALUE st);
56static inline void RSTRUCT_SET_RAW(VALUE st, long k, VALUE v);
57static inline VALUE RSTRUCT_GET_RAW(VALUE st, long k);
58
59static inline long
60RSTRUCT_EMBED_LEN(VALUE st)
61{
62 long ret = FL_TEST_RAW(st, RSTRUCT_EMBED_LEN_MASK);
63 ret >>= RSTRUCT_EMBED_LEN_SHIFT;
64 return ret;
65}
66
67static inline long
68RSTRUCT_LEN_RAW(VALUE st)
69{
70 if (FL_TEST_RAW(st, RSTRUCT_EMBED_LEN_MASK)) {
71 return RSTRUCT_EMBED_LEN(st);
72 }
73 else {
74 return RSTRUCT(st)->as.heap.len;
75 }
76}
77
78static inline int
79RSTRUCT_LENINT(VALUE st)
80{
81 return rb_long2int(RSTRUCT_LEN_RAW(st));
82}
83
84static inline const VALUE *
85RSTRUCT_CONST_PTR(VALUE st)
86{
87 const struct RStruct *p = RSTRUCT(st);
88
89 if (FL_TEST_RAW(st, RSTRUCT_EMBED_LEN_MASK)) {
90 return p->as.ary;
91 }
92 else {
93 return p->as.heap.ptr;
94 }
95}
96
97static inline void
98RSTRUCT_SET_RAW(VALUE st, long k, VALUE v)
99{
100 RB_OBJ_WRITE(st, &RSTRUCT_CONST_PTR(st)[k], v);
101}
102
103static inline VALUE
104RSTRUCT_GET_RAW(VALUE st, long k)
105{
106 return RSTRUCT_CONST_PTR(st)[k];
107}
108
109static inline VALUE
110RSTRUCT_FIELDS_OBJ(VALUE st)
111{
112 return RSTRUCT(st)->fields_obj;
113}
114
115static inline void
116RSTRUCT_SET_FIELDS_OBJ(VALUE st, VALUE fields_obj)
117{
118 RB_OBJ_WRITE(st, &RSTRUCT(st)->fields_obj, fields_obj);
119}
120#endif /* INTERNAL_STRUCT_H */
@ RUBY_FL_USHIFT
Number of bits in ruby_fl_type that are not open to users.
Definition fl_type.h:146
@ 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:456
int off
Offset inside of ptr.
Definition io.h:5
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 ID
Type that represents a Ruby identifier such as a variable name.
Definition value.h:52
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40