Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 203f021

Browse files
committedJun 15, 2015
Backport C-API needed for OpenSSL C-ext 2.x.
1 parent a97b41b commit 203f021

File tree

8 files changed

+425
-20
lines changed

8 files changed

+425
-20
lines changed
 

‎vm/builtin/data.cpp

+49-4
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ namespace rubinius {
3333
RDataShadow* rdata = reinterpret_cast<RDataShadow*>(handle->as_rdata(0));
3434

3535
rdata->data = data_ptr;
36-
rdata->dmark = mark;
37-
rdata->dfree = free;
36+
rdata->d.untyped.dmark = mark;
37+
rdata->d.untyped.dfree = free;
3838

3939
data->internal_ = rdata;
4040

@@ -47,16 +47,60 @@ namespace rubinius {
4747
return data;
4848
}
4949

50+
Data* Data::create_typed(STATE, void* data_ptr, const struct rb_data_type_struct_shadow* type) {
51+
Data* data;
52+
53+
data = state->new_object<Data>(G(data));
54+
data->freed_ = false;
55+
56+
// Data is just a heap alias for the handle, so go ahead and create
57+
// the handle and populate it as an RData now.
58+
capi::Handle* handle = data->handle(state);
59+
60+
assert(!handle && "can't already have a handle, it's brand new!");
61+
62+
handle = state->memory()->add_capi_handle(state, data);
63+
64+
// Don't call ->ref() on handle! We don't want the handle to keep the object
65+
// alive by default. The handle needs to have the lifetime of the object.
66+
67+
RDataShadow* rdata = reinterpret_cast<RDataShadow*>(handle->as_rtypeddata(0));
68+
69+
rdata->data = data_ptr;
70+
rdata->d.typed.typed = 1;
71+
rdata->d.typed.type = type;
72+
73+
data->internal_ = rdata;
74+
75+
if(type->function.dmark || type->function.dfree) {
76+
state->memory()->needs_finalization(data, (FinalizerFunction)&Data::finalize);
77+
}
78+
79+
state->vm()->metrics().m.ruby_metrics.memory_data_objects_total++;
80+
81+
return data;
82+
}
83+
5084
void* Data::data() {
5185
return rdata()->data;
5286
}
5387

5488
Data::FreeFunctor Data::free() {
55-
return rdata()->dfree;
89+
RDataShadow* data = rdata();
90+
if(typed()) {
91+
return data->d.typed.type->function.dfree;
92+
} else {
93+
return data->d.untyped.dfree;
94+
}
5695
}
5796

5897
Data::MarkFunctor Data::mark() {
59-
return rdata()->dmark;
98+
RDataShadow* data = rdata();
99+
if(typed()) {
100+
return data->d.typed.type->function.dmark;
101+
} else {
102+
return data->d.untyped.dmark;
103+
}
60104
}
61105

62106
void Data::finalize(STATE, Data* data) {
@@ -126,4 +170,5 @@ namespace rubinius {
126170
capi::set_current_mark(cur);
127171
}
128172
}
173+
129174
}

‎vm/builtin/data.hpp

+46-1
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,40 @@ namespace rubinius {
77
// Copied from here because you can't include capi/include/ruby.h into
88
// our C++ files.
99

10-
struct RDataShadow {
10+
struct rb_data_type_struct_shadow {
11+
const char *wrap_struct_name;
12+
struct {
13+
void (*dmark)(void*);
14+
void (*dfree)(void*);
15+
size_t (*dsize)(const void *);
16+
void *reserved[2]; /* For future extension.
17+
This array *must* be filled with ZERO. */
18+
} function;
19+
const struct rb_data_type_struct_shadow* parent;
20+
void *data; /* This area can be used for any purpose
21+
by a programmer who define the type. */
22+
};
23+
24+
// This union crazyness is needed because these should be compatible
25+
// for the data pointer. It is valid behavior to use DATA_PTR on both
26+
// typed and untyped and get a valid result back.
27+
// MRI constructs this differently, but this approach allows us to
28+
// use this in a slightly more type safe and explicit way.
29+
struct RUntypedDataShadow {
1130
void (*dmark)(void*);
1231
void (*dfree)(void*);
32+
};
33+
34+
struct RTypedDataShadow {
35+
const struct rb_data_type_struct_shadow* type;
36+
native_int typed;
37+
};
38+
39+
struct RDataShadow {
40+
union {
41+
RUntypedDataShadow untyped;
42+
RTypedDataShadow typed;
43+
} d;
1344
void *data;
1445
};
1546

@@ -36,6 +67,9 @@ namespace rubinius {
3667
/** New Data instance. */
3768
static Data* create(STATE, void* data, MarkFunctor mark, FreeFunctor free);
3869

70+
/** New typed Data instance. */
71+
static Data* create_typed(STATE, void* data, const struct rb_data_type_struct_shadow* type);
72+
3973
static void finalize(STATE, Data* data);
4074

4175
bool freed_p() const {
@@ -54,6 +88,17 @@ namespace rubinius {
5488
return internal_;
5589
}
5690

91+
bool typed() {
92+
return rdata()->d.typed.typed == 1;
93+
}
94+
95+
const struct rb_data_type_struct_shadow* data_type() {
96+
if(typed()) {
97+
return rdata()->d.typed.type;
98+
}
99+
return NULL;
100+
}
101+
57102
void* data();
58103
FreeFunctor free();
59104
MarkFunctor mark();

‎vm/capi/data.cpp

+77
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,29 @@ namespace rubinius {
3333
return rdata;
3434
}
3535
}
36+
37+
RTypedData* Handle::as_rtypeddata(NativeMethodEnvironment* env) {
38+
Data* data = c_as<Data>(object_);
39+
40+
if(data->freed_p()) {
41+
rb_raise(rb_eArgError, "Data object has already been freed");
42+
}
43+
44+
if(type_ == cRData) {
45+
return as_.rtypeddata;
46+
} else {
47+
type_ = cRData;
48+
49+
RTypedData* rtypeddata = new RTypedData;
50+
rtypeddata->data = 0;
51+
rtypeddata->type = 0;
52+
rtypeddata->typed_flag = 1;
53+
54+
as_.rtypeddata = rtypeddata;
55+
56+
return rtypeddata;
57+
}
58+
}
3659
}
3760
}
3861

@@ -60,4 +83,58 @@ extern "C" {
6083

6184
return env->get_handle(data);
6285
}
86+
87+
struct RTypedData* capi_rtypeddata_struct(VALUE data_handle) {
88+
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
89+
90+
Handle* handle = Handle::from(data_handle);
91+
env->check_tracked_handle(handle, false);
92+
93+
return handle->as_rtypeddata(env);
94+
}
95+
96+
VALUE rb_data_typed_object_alloc(VALUE klass, void* ptr, const rb_data_type_t* type) {
97+
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
98+
99+
if(!klass) klass = rb_cObject;
100+
101+
Class* data_klass = c_as<Class>(env->get_object(klass));
102+
103+
Data* data = Data::create_typed(env->state(), ptr, reinterpret_cast<const struct rb_data_type_struct_shadow*>(type));
104+
105+
data->klass(env->state(), data_klass);
106+
107+
return env->get_handle(data);
108+
}
109+
110+
int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent) {
111+
while (child) {
112+
if (child == parent) return 1;
113+
child = child->parent;
114+
}
115+
return 0;
116+
}
117+
118+
void* rb_check_typeddata(VALUE obj, const rb_data_type_t* data_type) {
119+
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
120+
const char* mesg = "wrong argument type %s (expected %s)";
121+
Data* data = c_as<Data>(env->get_object(obj));
122+
if(!data->typed()) {
123+
rb_raise(rb_eTypeError, mesg, rb_obj_classname(obj), data_type->wrap_struct_name);
124+
}
125+
126+
const rb_data_type_t* other_type = reinterpret_cast<const rb_data_type_t*>(data->data_type());
127+
128+
if (!rb_typeddata_inherited_p(other_type, data_type)) {
129+
rb_raise(rb_eTypeError, mesg, other_type->wrap_struct_name, data_type->wrap_struct_name);
130+
}
131+
return data->data();
132+
}
133+
134+
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type) {
135+
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
136+
Data* data = try_as<Data>(env->get_object(obj));
137+
if(!data || !data->typed()) return 0;
138+
return rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type);
139+
}
63140
}

‎vm/capi/file.cpp

+27
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,38 @@ extern "C" {
2828
return Handle::from(file)->as_rfile(env);
2929
}
3030

31+
int rb_cloexec_dup(int fd) {
32+
return fcntl(fd, F_DUPFD_CLOEXEC, 3);
33+
}
34+
3135
VALUE rb_file_open(const char* name, const char* mode) {
3236
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
3337
VALUE n = env->get_handle(String::create(env->state(), name));
3438
VALUE m = env->get_handle(String::create(env->state(), mode));
3539

3640
return rb_funcall(rb_cFile, rb_intern("open"), 2, n, m);
3741
}
42+
43+
FILE * rb_io_stdio_file(rb_io_t *fptr) {
44+
return fptr->f;
45+
}
46+
47+
VALUE rb_file_path_value(volatile VALUE* obj) {
48+
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
49+
STATE = env->state();
50+
51+
if(!kind_of<String>(env->get_object(*obj))) {
52+
*obj = rb_funcall(env->get_handle(G(type)), rb_intern("coerce_to_path"), 1, *obj);
53+
}
54+
55+
return *obj;
56+
}
57+
58+
VALUE rb_file_open_str(VALUE name, const char* mode) {
59+
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
60+
VALUE m = env->get_handle(String::create(env->state(), mode));
61+
62+
FilePathValue(name);
63+
return rb_funcall(rb_cFile, rb_intern("open"), 2, name, m);
64+
}
3865
}

‎vm/capi/handle.hpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
#include "detection.hpp"
55

6-
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070
6+
#if defined(__APPLE__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070
77
#ifndef RBX_HAVE_TR1_HASH
88
#include "missing/leopard_hashtable.hpp"
99
#endif
@@ -23,6 +23,7 @@
2323
struct RArray;
2424
struct RString;
2525
struct RData;
26+
struct RTypedData;
2627
struct RFloat;
2728
struct RIO;
2829
struct RFile;
@@ -58,6 +59,7 @@ namespace rubinius {
5859
RArray* rarray;
5960
RString* rstring;
6061
RData* rdata;
62+
RTypedData* rtypeddata;
6163
RFloat* rfloat;
6264
RIO* rio;
6365
RFile* rfile;
@@ -191,6 +193,7 @@ namespace rubinius {
191193
}
192194

193195
RData* as_rdata(NativeMethodEnvironment* env);
196+
RTypedData* as_rtypeddata(NativeMethodEnvironment* env);
194197
RArray* as_rarray(NativeMethodEnvironment* env);
195198
RString* as_rstring(NativeMethodEnvironment* env, int cache_level);
196199
RFloat* as_rfloat(NativeMethodEnvironment* env);

‎vm/capi/hash.cpp

+13-2
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,16 @@ extern "C" {
4343
}
4444

4545
VALUE rb_hash_lookup(VALUE self, VALUE key) {
46-
VALUE entry = capi_fast_call(self, rb_intern("find_item"), 1, key);
46+
return rb_hash_lookup2(self, key, Qnil);
47+
}
48+
49+
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def) {
50+
VALUE entry = capi_fast_call(hash, rb_intern("find_item"), 1, key);
51+
4752
if(entry != Qnil) {
4853
return capi_fast_call(entry, rb_intern("value"), 0);
4954
} else {
50-
return Qnil;
55+
return def;
5156
}
5257
}
5358

@@ -83,4 +88,10 @@ extern "C" {
8388
}
8489
}
8590
}
91+
92+
VALUE rb_hash_set_ifnone(VALUE hash, VALUE def) {
93+
capi_fast_call(hash, rb_intern("default="), 1, def);
94+
95+
return hash;
96+
}
8697
}

‎vm/capi/symbol.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,8 @@ extern "C" {
4040
Object* p = reinterpret_cast<Symbol*>(sym)->is_cvar_p(env->state());
4141
return CBOOL(p) ? Qtrue : Qfalse;
4242
}
43+
44+
VALUE rb_sym2str(VALUE sym) {
45+
return rb_id2str(SYM2ID(sym));
46+
}
4347
}

‎vm/include/capi/ruby.h

+205-12
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,101 @@
8989
# endif
9090
#endif
9191

92-
#define LONG_LONG long long
92+
#if SIZEOF_LONG_LONG > 0
93+
# define LONG_LONG long long
94+
#endif
95+
96+
#if SIZEOF_LONG == SIZEOF_VOIDP
97+
# define SIGNED_VALUE long
98+
# define SIZEOF_VALUE SIZEOF_LONG
99+
# define PRI_VALUE_PREFIX "l"
100+
#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
101+
# define SIGNED_VALUE LONG_LONG
102+
# define LONG_LONG_VALUE 1
103+
# define SIZEOF_VALUE SIZEOF_LONG_LONG
104+
# define PRI_VALUE_PREFIX "ll"
105+
#else
106+
# error ---->> ruby requires sizeof(void*) == sizeof(long) to be compiled. <<----
107+
#endif
108+
109+
#ifndef PRI_INT_PREFIX
110+
#define PRI_INT_PREFIX ""
111+
#endif
112+
#ifndef PRI_LONG_PREFIX
113+
#define PRI_LONG_PREFIX "l"
114+
#endif
115+
116+
#if SIZEOF_LONG == 8
117+
#define PRI_64_PREFIX PRI_LONG_PREFIX
118+
#elif SIZEOF_LONG_LONG == 8
119+
#define PRI_64_PREFIX PRI_LL_PREFIX
120+
#endif
121+
122+
#define RUBY_PRI_VALUE_MARK "\v"
123+
#if defined PRIdPTR && !defined PRI_VALUE_PREFIX
124+
#define PRIdVALUE PRIdPTR
125+
#define PRIoVALUE PRIoPTR
126+
#define PRIuVALUE PRIuPTR
127+
#define PRIxVALUE PRIxPTR
128+
#define PRIXVALUE PRIXPTR
129+
#define PRIsVALUE PRIiPTR"" RUBY_PRI_VALUE_MARK
130+
#else
131+
#define PRIdVALUE PRI_VALUE_PREFIX"d"
132+
#define PRIoVALUE PRI_VALUE_PREFIX"o"
133+
#define PRIuVALUE PRI_VALUE_PREFIX"u"
134+
#define PRIxVALUE PRI_VALUE_PREFIX"x"
135+
#define PRIXVALUE PRI_VALUE_PREFIX"X"
136+
#define PRIsVALUE PRI_VALUE_PREFIX"i" RUBY_PRI_VALUE_MARK
137+
#endif
138+
#ifndef PRI_VALUE_PREFIX
139+
# define PRI_VALUE_PREFIX ""
140+
#endif
141+
142+
#ifndef PRI_TIMET_PREFIX
143+
# if SIZEOF_TIME_T == SIZEOF_INT
144+
# define PRI_TIMET_PREFIX
145+
# elif SIZEOF_TIME_T == SIZEOF_LONG
146+
# define PRI_TIMET_PREFIX "l"
147+
# elif SIZEOF_TIME_T == SIZEOF_LONG_LONG
148+
# define PRI_TIMET_PREFIX PRI_LL_PREFIX
149+
# endif
150+
#endif
151+
152+
#if defined PRI_PTRDIFF_PREFIX
153+
#elif SIZEOF_PTRDIFF_T == SIZEOF_INT
154+
# define PRI_PTRDIFF_PREFIX ""
155+
#elif SIZEOF_PTRDIFF_T == SIZEOF_LONG
156+
# define PRI_PTRDIFF_PREFIX "l"
157+
#elif SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG
158+
# define PRI_PTRDIFF_PREFIX PRI_LL_PREFIX
159+
#endif
160+
#define PRIdPTRDIFF PRI_PTRDIFF_PREFIX"d"
161+
#define PRIiPTRDIFF PRI_PTRDIFF_PREFIX"i"
162+
#define PRIoPTRDIFF PRI_PTRDIFF_PREFIX"o"
163+
#define PRIuPTRDIFF PRI_PTRDIFF_PREFIX"u"
164+
#define PRIxPTRDIFF PRI_PTRDIFF_PREFIX"x"
165+
#define PRIXPTRDIFF PRI_PTRDIFF_PREFIX"X"
166+
167+
#if defined PRI_SIZE_PREFIX
168+
#elif SIZEOF_SIZE_T == SIZEOF_INT
169+
# define PRI_SIZE_PREFIX ""
170+
#elif SIZEOF_SIZE_T == SIZEOF_LONG
171+
# define PRI_SIZE_PREFIX "l"
172+
#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
173+
# define PRI_SIZE_PREFIX PRI_LL_PREFIX
174+
#endif
175+
#define PRIdSIZE PRI_SIZE_PREFIX"d"
176+
#define PRIiSIZE PRI_SIZE_PREFIX"i"
177+
#define PRIoSIZE PRI_SIZE_PREFIX"o"
178+
#define PRIuSIZE PRI_SIZE_PREFIX"u"
179+
#define PRIxSIZE PRI_SIZE_PREFIX"x"
180+
#define PRIXSIZE PRI_SIZE_PREFIX"X"
181+
182+
#ifdef __GNUC__
183+
#define RB_UNUSED_VAR(x) x __attribute__ ((unused))
184+
#else
185+
#define RB_UNUSED_VAR(x) x
186+
#endif
93187

94188
#ifndef RUBY_EXTERN
95189
#define RUBY_EXTERN extern
@@ -219,6 +313,9 @@ struct RString {
219313
#define RSTRING(str) capi_rstring_struct(str, RSTRING_CACHE_UNSAFE)
220314
#endif
221315

316+
#define RSTRING_GETMEM(rb_str, c_str, c_str_len) \
317+
((c_str) = RSTRING_PTR(rb_str), (c_str_len) = RSTRING_LEN(rb_str))
318+
222319
struct RArray {
223320
ssize_t len;
224321
struct {
@@ -238,6 +335,7 @@ struct RData {
238335
};
239336

240337
#define RDATA(d) capi_rdata_struct(d)
338+
#define RTYPEDDATA(d) capi_rtypeddata_struct(d)
241339

242340
struct RFloat {
243341
double value;
@@ -250,6 +348,8 @@ struct RFloat {
250348
#define RHASH(obj) ({ C_API_RHASH_is_not_supported_in_Rubinius })
251349
#define RHASH_TBL(obj) ({ C_API_RHASH_TBL_is_not_supported_in_Rubinius })
252350

351+
#define RHASH_SET_IFNONE(hash, def) rb_hash_set_ifnone(hash, def)
352+
253353
typedef struct rb_io_t {
254354
VALUE handle;
255355
int fd;
@@ -381,9 +481,19 @@ struct RFile {
381481
/** Reallocate memory allocated with ALLOC or ALLOC_N. */
382482
#define REALLOC_N(ptr, type, n) (ptr)=(type*)realloc(ptr, sizeof(type) * (n));
383483

484+
#define ZALLOC_N(type,n) ((type*)xcalloc((n),sizeof(type)))
485+
#define ZALLOC(type) (ZALLOC_N(type,1))
486+
487+
#define ALLOCV(v, n) rb_alloc_tmp_buffer(&(v), (n))
488+
#define ALLOCV_N(type, v, n) ((type*)ALLOCV((v), sizeof(type)*(n)))
489+
#define ALLOCV_END(v) rb_free_tmp_buffer(&(v))
490+
384491
/** Interrupt checking (no-op). */
385492
#define CHECK_INTS /* No-op */
386493

494+
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg) \
495+
VALUE yielded_arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg
496+
387497
/** Rubinius doesn't need gc guards */
388498
#define RB_GC_GUARD /* No-op */
389499

@@ -482,6 +592,7 @@ VALUE rb_uint2big(unsigned long number);
482592

483593
/** The length of string str. */
484594
#define RSTRING_LEN(str) rb_str_len(str)
595+
#define RSTRING_LENINT(str) rb_str_len(str)
485596

486597
/** The pointer to the string str's data. */
487598
#ifdef RUBY_READONLY_STRING
@@ -513,11 +624,15 @@ VALUE rb_uint2big(unsigned long number);
513624

514625
#define Check_SafeStr(x)
515626

627+
#define FilePathValue(v) rb_file_path_value(&(v))
628+
516629
/** Retrieve the ID given a Symbol handle. */
517630
#define SYM2ID(sym) (sym)
518631

519632
/** Return an integer type id for the object. @see rb_type() */
520633
#define TYPE(handle) rb_type(handle)
634+
#define rb_type_p(obj, type) (rb_type(obj) == (type))
635+
#define RB_TYPE_P(obj, type) rb_type_p(obj, type)
521636

522637
/** Alias to rb_type. This is not exactly the same as in MRI, but it makes sure
523638
+ * that it won't segfault if you give BUILTIN_TYPE an immediate such as a Fixnum
@@ -592,6 +707,7 @@ VALUE rb_uint2big(unsigned long number);
592707

593708
struct RArray* capi_rarray_struct(VALUE array);
594709
struct RData* capi_rdata_struct(VALUE data);
710+
struct RTypedData* capi_rtypeddata_struct(VALUE data);
595711
struct RString* capi_rstring_struct(VALUE string, int cache_level);
596712
struct RFloat* capi_rfloat_struct(VALUE data);
597713
struct RIO* capi_rio_struct(VALUE handle);
@@ -625,19 +741,78 @@ VALUE rb_uint2big(unsigned long number);
625741
VALUE rb_equal(VALUE a, VALUE b);
626742
VALUE rb_class_inherited_p(VALUE mod, VALUE arg);
627743

628-
#define Data_Make_Struct(klass, type, mark, free, sval) (\
629-
sval = ALLOC(type), \
630-
memset(sval, 0, sizeof(type)), \
631-
Data_Wrap_Struct(klass, mark, free, sval)\
632-
)
744+
typedef struct rb_data_type_struct rb_data_type_t;
745+
746+
struct rb_data_type_struct {
747+
const char *wrap_struct_name;
748+
struct {
749+
void (*dmark)(void*);
750+
void (*dfree)(void*);
751+
size_t (*dsize)(const void *);
752+
void *reserved[2]; /* For future extension.
753+
This array *must* be filled with ZERO. */
754+
} function;
755+
const rb_data_type_t *parent;
756+
void *data; /* This area can be used for any purpose
757+
by a programmer who define the type. */
758+
VALUE flags; /* FL_WB_PROTECTED */
759+
};
760+
761+
#define HAVE_TYPE_RB_DATA_TYPE_T 1
762+
#define HAVE_RB_DATA_TYPE_T_FUNCTION 1
763+
#define HAVE_RB_DATA_TYPE_T_PARENT 1
764+
765+
struct RTypedData {
766+
const rb_data_type_t *type;
767+
VALUE typed_flag; /* 1 or not */
768+
void *data;
769+
};
633770

634-
#define Data_Wrap_Struct(klass, mark, free, sval) \
635-
rb_data_object_alloc(klass, (void*)sval, (RUBY_DATA_FUNC)mark, \
636-
(RUBY_DATA_FUNC)free)
771+
#define RTYPEDDATA_P(v) (RTYPEDDATA(v)->typed_flag == 1)
772+
#define RTYPEDDATA_TYPE(v) (RTYPEDDATA(v)->type)
773+
#define RTYPEDDATA_DATA(v) (RTYPEDDATA(v)->data)
774+
775+
VALUE rb_data_object_alloc(VALUE,void*,RUBY_DATA_FUNC,RUBY_DATA_FUNC);
776+
VALUE rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *);
777+
int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent);
778+
int rb_typeddata_is_kind_of(VALUE, const rb_data_type_t *);
779+
void *rb_check_typeddata(VALUE, const rb_data_type_t *);
780+
781+
#define Check_TypedStruct(v,t) rb_check_typeddata((VALUE)(v),(t))
782+
#define RUBY_DEFAULT_FREE ((RUBY_DATA_FUNC)-1)
783+
#define RUBY_NEVER_FREE ((RUBY_DATA_FUNC)0)
784+
#define RUBY_TYPED_DEFAULT_FREE RUBY_DEFAULT_FREE
785+
#define RUBY_TYPED_NEVER_FREE RUBY_NEVER_FREE
786+
787+
/* bits for rb_data_type_struct::flags */
788+
#define RUBY_TYPED_FREE_IMMEDIATELY 0xcafebeef
789+
#define RUBY_TYPED_WB_PROTECTED 0xbeefcafe
790+
791+
#define Data_Wrap_Struct(klass,mark,free,sval)\
792+
rb_data_object_alloc((klass),(sval),(RUBY_DATA_FUNC)(mark),(RUBY_DATA_FUNC)(free))
793+
794+
#define Data_Make_Struct(klass,type,mark,free,sval) (\
795+
(sval) = ALLOC(type),\
796+
memset((sval), 0, sizeof(type)),\
797+
Data_Wrap_Struct((klass),(mark),(free),(sval))\
798+
)
799+
800+
#define TypedData_Wrap_Struct(klass,data_type,sval)\
801+
rb_data_typed_object_alloc((klass),(sval),(data_type))
802+
803+
#define TypedData_Make_Struct(klass, type, data_type, sval) (\
804+
(sval) = ALLOC(type),\
805+
memset((sval), 0, sizeof(type)),\
806+
TypedData_Wrap_Struct((klass),(data_type),(sval))\
807+
)
808+
809+
#define Data_Get_Struct(obj,type,sval) do {\
810+
Check_Type((obj), T_DATA); \
811+
(sval) = (type*)DATA_PTR(obj);\
812+
} while (0)
637813

638-
#define Data_Get_Struct(obj,type,sval) do {\
639-
Check_Type(obj, T_DATA); \
640-
sval = (type*)DATA_PTR(obj);\
814+
#define TypedData_Get_Struct(obj,type,data_type,sval) do {\
815+
(sval) = (type*)rb_check_typeddata((obj), (data_type)); \
641816
} while (0)
642817

643818
/** Return Qtrue if obj is an immediate, Qfalse or Qnil. */
@@ -859,6 +1034,7 @@ VALUE rb_uint2big(unsigned long number);
8591034

8601035
/** Returns String representation of the class' name. */
8611036
VALUE rb_class_name(VALUE klass);
1037+
#define rb_class_path(k) rb_class_name(k)
8621038

8631039
/** Calls the class method 'inherited' on super passing the class.
8641040
* If super is NULL, calls Object.inherited. */
@@ -874,6 +1050,9 @@ VALUE rb_uint2big(unsigned long number);
8741050
/** Returns the Class object this object is an instance of. */
8751051
VALUE rb_class_of(VALUE object);
8761052

1053+
/** Returns the superclass of a class. */
1054+
VALUE rb_class_superclass(VALUE klass);
1055+
8771056
/** Returns the first superclass of an object that isn't a singleton or
8781057
* intermediate.
8791058
*/
@@ -1061,6 +1240,9 @@ VALUE rb_uint2big(unsigned long number);
10611240

10621241
VALUE rb_vsprintf(const char *format, va_list varargs);
10631242

1243+
/** Returns a duplicate file discriptor with close-on-exec flag set. */
1244+
int rb_cloexec_dup(int fd);
1245+
10641246
/** Returns a File opened with the specified mode. */
10651247
VALUE rb_file_open(const char* name, const char* mode);
10661248

@@ -1115,6 +1297,8 @@ VALUE rb_uint2big(unsigned long number);
11151297
/** Return the value associated with the key, excluding default values. */
11161298
VALUE rb_hash_lookup(VALUE self, VALUE key);
11171299

1300+
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def);
1301+
11181302
/** Set the value associated with the key. */
11191303
VALUE rb_hash_aset(VALUE self, VALUE key, VALUE value);
11201304

@@ -1136,6 +1320,8 @@ VALUE rb_uint2big(unsigned long number);
11361320
int (*func)(ANYARGS),
11371321
VALUE farg);
11381322

1323+
VALUE rb_hash_set_ifnone(VALUE hash, VALUE def);
1324+
11391325
void rb_eof_error();
11401326

11411327
VALUE rb_io_addstr(VALUE, VALUE);
@@ -1233,6 +1419,8 @@ VALUE rb_uint2big(unsigned long number);
12331419
ID rb_intern(const char* string);
12341420
ID rb_intern2(const char* string, long len);
12351421

1422+
VALUE rb_sym2str(VALUE sym);
1423+
12361424
/** Coerce x and y and perform 'x func y' */
12371425
VALUE rb_num_coerce_bin(VALUE x, VALUE y, ID func);
12381426

@@ -1572,6 +1760,9 @@ VALUE rb_uint2big(unsigned long number);
15721760
* to check that length is greater than 0 properly */
15731761
VALUE rb_str_new(const char* string, long length);
15741762

1763+
/** Create a String from a C string. Alias of rb_str_new2. */
1764+
VALUE rb_str_new_cstr(const char* string);
1765+
15751766
/** Create a String from a C string. */
15761767
VALUE rb_str_new2(const char* string);
15771768

@@ -1760,6 +1951,8 @@ VALUE rb_uint2big(unsigned long number);
17601951

17611952
NORETURN(void rb_notimplement());
17621953

1954+
NORETURN(VALUE rb_f_notimplement(int argc, VALUE *argv, VALUE obj));
1955+
17631956
/** Raises an ArgumentError exception. */
17641957
NORETURN(void rb_invalid_str(const char *str, const char *type));
17651958

0 commit comments

Comments
 (0)
Please sign in to comment.