summaryrefslogtreecommitdiff
path: root/include/ruby/internal/intern/struct.h
blob: 16b3fad4e0878d0ed174ac98b1464ecd4184660a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#ifndef RBIMPL_INTERN_STRUCT_H                       /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_INTERN_STRUCT_H
/**
 * @file
 * @author     Ruby developers <ruby-core@ruby-lang.org>
 * @copyright  This  file  is   a  part  of  the   programming  language  Ruby.
 *             Permission  is hereby  granted,  to  either redistribute  and/or
 *             modify this file, provided that  the conditions mentioned in the
 *             file COPYING are met.  Consult the file for details.
 * @warning    Symbols   prefixed  with   either  `RBIMPL`   or  `rbimpl`   are
 *             implementation details.   Don't take  them as canon.  They could
 *             rapidly appear then vanish.  The name (path) of this header file
 *             is also an  implementation detail.  Do not expect  it to persist
 *             at the place it is now.  Developers are free to move it anywhere
 *             anytime at will.
 * @note       To  ruby-core:  remember  that   this  header  can  be  possibly
 *             recursively included  from extension  libraries written  in C++.
 *             Do not  expect for  instance `__VA_ARGS__` is  always available.
 *             We assume C99  for ruby itself but we don't  assume languages of
 *             extension libraries.  They could be written in C++98.
 * @brief      Public APIs related to ::rb_cStruct.
 */
#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/intern/vm.h" /* rb_alloc_func_t */
#include "ruby/internal/value.h"

RBIMPL_SYMBOL_EXPORT_BEGIN()

/* struct.c */

/**
 * Creates an instance of the given struct.
 *
 * @param[in]  klass  The class of the instance to allocate.
 * @param[in]  ...    The fields.
 * @return     Allocated instance of `klass`.
 * @pre        `klass` must be a subclass of ::rb_cStruct.
 * @note       Number of variadic arguments must much that of the passed klass'
 *             fields.
 */
VALUE rb_struct_new(VALUE klass, ...);

/**
 * Defines a struct class.
 *
 * @param[in]  name           Name of the class.
 * @param[in]  ...            Arbitrary number of  `const char*`, terminated by
 *                            NULL.  Each of which are the name of fields.
 * @exception  rb_eNameError  `name` is not a constant name.
 * @exception  rb_eTypeError  `name` is already taken.
 * @exception  rb_eArgError   Duplicated field name.
 * @return     The defined class.
 * @post       Global toplevel constant `name` is defined.
 * @note       `name` is allowed  to be a null pointer.   This function creates
 *             an anonymous struct class then.
 * @note       The GC does not collect nor move classes returned by this
 *             function. They are immortal.
 *
 * @internal
 *
 * Not  seriously  checked but  it  seems  this  function  does not  share  its
 * implementation with how `Struct.new` is implemented...?
 */
VALUE rb_struct_define(const char *name, ...);

RBIMPL_ATTR_NONNULL((2))
/**
 * Identical  to rb_struct_define(),  except  it defines  the  class under  the
 * specified namespace instead of global toplevel.
 *
 * @param[out]  space          Namespace that the defining class shall reside.
 * @param[in]   name           Name of the class.
 * @param[in]   ...            Arbitrary number of `const char*`, terminated by
 *                             NULL.  Each of which are the name of fields.
 * @exception   rb_eNameError  `name` is not a constant name.
 * @exception   rb_eTypeError  `name` is already taken.
 * @exception   rb_eArgError   Duplicated field name.
 * @return      The defined class.
 * @post        `name` is a constant under `space`.
 * @note        In contrast to rb_struct_define(), it doesn't make any sense to
 *              pass  a null pointer to this function.
 * @note        The GC does not collect nor move classes returned by this
 *              function. They are immortal.
 */
VALUE rb_struct_define_under(VALUE space, const char *name, ...);

/**
 * Identical to  rb_struct_new(), except it  takes the  field values as  a Ruby
 * array.
 *
 * @param[in]  klass   The class of the instance to allocate.
 * @param[in]  values  Field values.
 * @return     Allocated instance of `klass`.
 * @pre        `klass` must be a subclass of ::rb_cStruct.
 * @pre        `values` must be an instance of struct ::RArray.
 */
VALUE rb_struct_alloc(VALUE klass, VALUE values);

/**
 * Mass-assigns a struct's fields.
 *
 * @param[out]  self    An instance of a struct class to squash.
 * @param[in]   values  New values.
 * @return      ::RUBY_Qnil.
 */
VALUE rb_struct_initialize(VALUE self, VALUE values);

/**
 * Identical to rb_struct_aref(), except it takes ::ID instead of ::VALUE.
 *
 * @param[in]  self           An instance of a struct class.
 * @param[in]  key            Key to query.
 * @exception  rb_eTypeError  `self` is not a struct.
 * @exception  rb_eNameError  No such field.
 * @return     The value stored at `key` in `self`.
 */
VALUE rb_struct_getmember(VALUE self, ID key);

/**
 * Queries the list of the names of the fields of the given struct class.
 *
 * @param[in]  klass  A subclass of ::rb_cStruct.
 * @return     The list of the names of the fields of `klass`.
 */
VALUE rb_struct_s_members(VALUE klass);

/**
 * Queries the list of the names of the fields of the class of the given struct
 * object.  This is  almost the same as calling  rb_struct_s_members() over the
 * class of the receiver.
 *
 * @internal
 *
 * "Almost"?  What exactly is the difference?
 *
 * @endinternal
 *
 * @param[in]  self  An instance of a subclass of ::rb_cStruct.
 * @return     The list of the names of the fields.
 */
VALUE rb_struct_members(VALUE self);

/**
 * Allocates an  instance of the  given class.   This consequential name  is of
 * course because rb_struct_alloc() not only  allocates but also initialises an
 * instance.  The API design is broken.
 *
 * @param[in]  klass  A subclass of ::rb_cStruct.
 * @return     An allocated instance of `klass`, not initialised.
 */
VALUE rb_struct_alloc_noinit(VALUE klass);

/**
 * Identical to rb_struct_define(), except it does not define accessor methods.
 * You  have to  define them  yourself.   Forget about  the allocator  function
 * parameter; it is  for internal use only.  Extension libraries  are unable to
 * properly allocate a ruby struct, because `RStruct` is opaque.
 *
 * @internal
 *
 * Several flags must be set up properly for ::RUBY_T_STRUCT objects, which are
 * also missing for extension libraries.
 *
 * @endinternal
 *
 * @param[in]  name           Name of the class.
 * @param[in]  super          Superclass of the defining class.
 * @param[in]  func           Must be 0 for extension libraries.
 * @param[in]  ...            Arbitrary number of  `const char*`, terminated by
 *                            NULL.  Each of which are the name of fields.
 * @exception  rb_eNameError  `name` is not a constant name.
 * @exception  rb_eTypeError  `name` is already taken.
 * @exception  rb_eArgError   Duplicated field name.
 * @return     The defined class.
 * @post       Global toplevel constant `name` is defined.
 * @note       `name` is allowed  to be a null pointer.   This function creates
 *             an anonymous struct class then.
 */
VALUE rb_struct_define_without_accessor(const char *name, VALUE super, rb_alloc_func_t func, ...);

RBIMPL_ATTR_NONNULL((2))
/**
 * Identical  to  rb_struct_define_without_accessor(),  except it  defines  the
 * class under the specified namespace instead of global toplevel.  It can also
 * be seen as  a routine identical to rb_struct_define_under(),  except it does
 * not define accessor methods.
 *
 * @param[out]  outer          Namespace that the defining class shall reside.
 * @param[in]   class_name     Name of the class.
 * @param[in]   super          Superclass of the defining class.
 * @param[in]   alloc          Must be 0 for extension libraries.
 * @param[in]   ...            Arbitrary number of `const char*`, terminated by
 *                             NULL.  Each of which are the name of fields.
 * @exception   rb_eNameError  `class_name` is not a constant name.
 * @exception   rb_eTypeError  `class_name` is already taken.
 * @exception   rb_eArgError   Duplicated field name.
 * @return      The defined class.
 * @post        `class_name` is a constant under `outer`.
 * @note        In contrast to  rb_struct_define_without_accessor(), it doesn't
 *              make any sense to pass a null name.
 * @note        The GC does not collect nor move classes returned by this
 *              function. They are immortal.
 */
VALUE rb_struct_define_without_accessor_under(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, ...);

/**
 * Defines an anonymous data class.
 *
 * @endinternal
 *
 * @param[in]  super           Superclass  of the  defining  class.   Must be  a
 *                             descendant of ::rb_cData, or 0 as ::rb_cData.
 * @param[in]  ...             Arbitrary number of  `const char*`, terminated by
 *                             NULL.  Each of which are the name of fields.
 * @exception  rb_eArgError    Duplicated field name.
 * @return     The defined class.
 * @note       The GC does not collect nor move classes returned by this
 *             function. They are immortal.
 */
VALUE rb_data_define(VALUE super, ...);

RBIMPL_SYMBOL_EXPORT_END()

#endif /* RBIMPL_INTERN_STRUCT_H */