-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrdata.h
373 lines (342 loc) · 13.3 KB
/
rdata.h
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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
#ifndef RBIMPL_RDATA_H /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_RDATA_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 Defines struct ::RData.
*/
#include "ruby/internal/config.h"
#ifdef STDC_HEADERS
# include <stddef.h>
#endif
#include "ruby/internal/attr/deprecated.h"
#include "ruby/internal/attr/warning.h"
#include "ruby/internal/cast.h"
#include "ruby/internal/core/rbasic.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/fl_type.h"
#include "ruby/internal/value.h"
#include "ruby/internal/value_type.h"
#include "ruby/defines.h"
/** @cond INTERNAL_MACRO */
#ifndef RUBY_UNTYPED_DATA_WARNING
#define RUBY_UNTYPED_DATA_WARNING 1
#endif
#define RBIMPL_DATA_FUNC(f) RBIMPL_CAST((void (*)(void *))(f))
#define RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() \
RBIMPL_ATTR_WARNING(("untyped Data is unsafe; use TypedData instead")) \
RBIMPL_ATTR_DEPRECATED(("by TypedData"))
#define RBIMPL_MACRO_SELECT(x, y) x ## y
#define RUBY_MACRO_SELECT(x, y) RBIMPL_MACRO_SELECT(x, y)
/** @endcond */
/**
* Convenient casting macro.
*
* @param obj An object, which is in fact an ::RData.
* @return The passed object casted to ::RData.
*/
#define RDATA(obj) RBIMPL_CAST((struct RData *)(obj))
/**
* Convenient getter macro.
*
* @param obj An object, which is in fact an ::RData.
* @return The passed object's ::RData::data field.
*/
#define DATA_PTR(obj) RDATA(obj)->data
/**
* This is a value you can set to ::RData::dfree. Setting this means the data
* was allocated using ::ruby_xmalloc() (or variants), and shall be freed using
* ::ruby_xfree().
*
* @warning Do not use this if you want to use system malloc, because the
* system and Ruby might or might not share the same malloc
* implementation.
*/
#define RUBY_DEFAULT_FREE RBIMPL_DATA_FUNC(-1)
/**
* This is a value you can set to ::RData::dfree. Setting this means the data
* is managed by someone else, like, statically allocated. Of course you are
* on your own then.
*/
#define RUBY_NEVER_FREE RBIMPL_DATA_FUNC(0)
/**
* @private
*
* @deprecated This macro once was a thing in the old days, but makes no sense
* any longer today. Exists here for backwards compatibility
* only. You can safely forget about it.
*/
#define RUBY_UNTYPED_DATA_FUNC(f) f RBIMPL_ATTRSET_UNTYPED_DATA_FUNC()
/*
#define RUBY_DATA_FUNC(func) ((void (*)(void*))(func))
*/
/**
* This is the type of callbacks registered to ::RData. The argument is the
* `data` field.
*/
typedef void (*RUBY_DATA_FUNC)(void*);
/**
* @deprecated
*
* Old "untyped" user data. It has roughly the same usage as struct
* ::RTypedData, but lacked several features such as support for compaction GC.
* Use of this struct is not recommended any longer. If it is dead necessary,
* please inform the core devs about your usage.
*
* @internal
*
* @shyouhei tried to add RBIMPL_ATTR_DEPRECATED for this type but that yielded
* too many warnings in the core. Maybe we want to retry later... Just add
* deprecated document for now.
*/
struct RData {
/** Basic part, including flags and class. */
struct RBasic basic;
/**
* This function is called when the object is experiencing GC marks. If it
* contains references to other Ruby objects, you need to mark them also.
* Otherwise GC will smash your data.
*
* @see rb_gc_mark()
* @warning This is called during GC runs. Object allocations are
* impossible at that moment (that is why GC runs).
*/
RUBY_DATA_FUNC dmark;
/**
* This function is called when the object is no longer used. You need to
* do whatever necessary to avoid memory leaks.
*
* @warning This is called during GC runs. Object allocations are
* impossible at that moment (that is why GC runs).
*/
RUBY_DATA_FUNC dfree;
/** Pointer to the actual C level struct that you want to wrap. */
void *data;
};
RBIMPL_SYMBOL_EXPORT_BEGIN()
/**
* This is the primitive way to wrap an existing C struct into ::RData.
*
* @param[in] klass Ruby level class of the returning object.
* @param[in] datap Pointer to the target C struct.
* @param[in] dmark Mark function.
* @param[in] dfree Free function.
* @exception rb_eTypeError `klass` is not a class.
* @exception rb_eNoMemError Out of memory.
* @return An allocated object that wraps `datap`.
*/
VALUE rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree);
/**
* Identical to rb_data_object_wrap(), except it allocates a new data region
* internally instead of taking an existing one. The allocation is done using
* ruby_calloc(). Hence it makes no sense to pass anything other than
* ::RUBY_DEFAULT_FREE to the last argument.
*
* @param[in] klass Ruby level class of the returning object.
* @param[in] size Requested size of memory to allocate.
* @param[in] dmark Mark function.
* @param[in] dfree Free function.
* @exception rb_eTypeError `klass` is not a class.
* @exception rb_eNoMemError Out of memory.
* @return An allocated object that wraps a new `size` byte region.
*/
VALUE rb_data_object_zalloc(VALUE klass, size_t size, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree);
/**
* @private
* Documented in include/ruby/internal/globals.h
*/
RUBY_EXTERN VALUE rb_cObject;
RBIMPL_SYMBOL_EXPORT_END()
/**
* Converts sval, a pointer to your struct, into a Ruby object.
*
* @param klass A ruby level class.
* @param mark Mark function.
* @param free Free function.
* @param sval A pointer to your struct.
* @exception rb_eTypeError `klass` is not a class.
* @exception rb_eNoMemError Out of memory.
* @return A created Ruby object.
*/
#define Data_Wrap_Struct(klass, mark, free, sval) \
rb_data_object_wrap( \
(klass), \
(sval), \
RBIMPL_DATA_FUNC(mark), \
RBIMPL_DATA_FUNC(free))
/**
* @private
*
* This is an implementation detail of #Data_Make_Struct. People don't use it
* directly.
*
* @param result Variable name of created Ruby object.
* @param klass Ruby level class of the object.
* @param type Type name of the C struct.
* @param size Size of the C struct.
* @param mark Mark function.
* @param free Free function.
* @param sval Variable name of created C struct.
*/
#define Data_Make_Struct0(result, klass, type, size, mark, free, sval) \
VALUE result = rb_data_object_zalloc( \
(klass), \
(size), \
RBIMPL_DATA_FUNC(mark), \
RBIMPL_DATA_FUNC(free)); \
(sval) = RBIMPL_CAST((type *)DATA_PTR(result)); \
RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval))
/**
* Identical to #Data_Wrap_Struct, except it allocates a new data region
* internally instead of taking an existing one. The allocation is done using
* ruby_calloc(). Hence it makes no sense to pass anything other than
* ::RUBY_DEFAULT_FREE to the `free` argument.
*
* @param klass Ruby level class of the returning object.
* @param type Type name of the C struct.
* @param mark Mark function.
* @param free Free function.
* @param sval Variable name of created C struct.
* @exception rb_eTypeError `klass` is not a class.
* @exception rb_eNoMemError Out of memory.
* @return A created Ruby object.
*/
#ifdef HAVE_STMT_AND_DECL_IN_EXPR
#define Data_Make_Struct(klass, type, mark, free, sval) \
RB_GNUC_EXTENSION({ \
Data_Make_Struct0( \
data_struct_obj, \
klass, \
type, \
sizeof(type), \
mark, \
free, \
sval); \
data_struct_obj; \
})
#else
#define Data_Make_Struct(klass, type, mark, free, sval) \
rb_data_object_make( \
(klass), \
RBIMPL_DATA_FUNC(mark), \
RBIMPL_DATA_FUNC(free), \
RBIMPL_CAST((void **)&(sval)), \
sizeof(type))
#endif
/**
* Obtains a C struct from inside of a wrapper Ruby object.
*
* @param obj An instance of ::RData.
* @param type Type name of the C struct.
* @param sval Variable name of obtained C struct.
* @return Unwrapped C struct that `obj` holds.
*/
#define Data_Get_Struct(obj, type, sval) \
((sval) = RBIMPL_CAST((type*)rb_data_object_get(obj)))
RBIMPL_ATTRSET_UNTYPED_DATA_FUNC()
/**
* @private
*
* This is an implementation detail of rb_data_object_wrap(). People don't use
* it directly.
*
* @param[in] klass Ruby level class of the returning object.
* @param[in] ptr Pointer to the target C struct.
* @param[in] mark Mark function.
* @param[in] free Free function.
* @exception rb_eTypeError `klass` is not a class.
* @exception rb_eNoMemError Out of memory.
* @return An allocated object that wraps `datap`.
*/
static inline VALUE
rb_data_object_wrap_warning(VALUE klass, void *ptr, RUBY_DATA_FUNC mark, RUBY_DATA_FUNC free)
{
return rb_data_object_wrap(klass, ptr, mark, free);
}
/**
* @private
*
* This is an implementation detail of #Data_Get_Struct. People don't use it
* directly.
*
* @param[in] obj An instance of ::RData.
* @return Unwrapped C struct that `obj` holds.
*/
static inline void *
rb_data_object_get(VALUE obj)
{
Check_Type(obj, RUBY_T_DATA);
return DATA_PTR(obj);
}
RBIMPL_ATTRSET_UNTYPED_DATA_FUNC()
/**
* @private
*
* This is an implementation detail of #Data_Get_Struct. People don't use it
* directly.
*
* @param[in] obj An instance of ::RData.
* @return Unwrapped C struct that `obj` holds.
*/
static inline void *
rb_data_object_get_warning(VALUE obj)
{
return rb_data_object_get(obj);
}
/**
* This is an implementation detail of #Data_Make_Struct. People don't use it
* directly.
*
* @param[in] klass Ruby level class of the returning object.
* @param[in] mark_func Mark function.
* @param[in] free_func Free function.
* @param[in] datap Variable of created C struct.
* @param[in] size Requested size of allocation.
* @exception rb_eTypeError `klass` is not a class.
* @exception rb_eNoMemError Out of memory.
* @return A created Ruby object.
* @post `*datap` holds the created C struct.
*/
static inline VALUE
rb_data_object_make(VALUE klass, RUBY_DATA_FUNC mark_func, RUBY_DATA_FUNC free_func, void **datap, size_t size)
{
Data_Make_Struct0(result, klass, void, size, mark_func, free_func, *datap);
return result;
}
RBIMPL_ATTR_DEPRECATED(("by: rb_data_object_wrap"))
/** @deprecated This function was renamed to rb_data_object_wrap(). */
static inline VALUE
rb_data_object_alloc(VALUE klass, void *data, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
{
return rb_data_object_wrap(klass, data, dmark, dfree);
}
/** @cond INTERNAL_MACRO */
#define rb_data_object_wrap_0 rb_data_object_wrap
#define rb_data_object_wrap_1 rb_data_object_wrap_warning
#define rb_data_object_wrap_2 rb_data_object_wrap_ /* Used here vvvv */
#define rb_data_object_wrap RUBY_MACRO_SELECT(rb_data_object_wrap_2, RUBY_UNTYPED_DATA_WARNING)
#define rb_data_object_get_0 rb_data_object_get
#define rb_data_object_get_1 rb_data_object_get_warning
#define rb_data_object_get_2 rb_data_object_get_ /* Used here vvvv */
#define rb_data_object_get RUBY_MACRO_SELECT(rb_data_object_get_2, RUBY_UNTYPED_DATA_WARNING)
#define rb_data_object_make_0 rb_data_object_make
#define rb_data_object_make_1 rb_data_object_make_warning
#define rb_data_object_make_2 rb_data_object_make_ /* Used here vvvv */
#define rb_data_object_make RUBY_MACRO_SELECT(rb_data_object_make_2, RUBY_UNTYPED_DATA_WARNING)
/** @endcond */
#endif /* RBIMPL_RDATA_H */