rice 4.3.3 → 4.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +63 -26
- data/README.md +7 -2
- data/Rakefile +7 -1
- data/include/rice/rice.hpp +7291 -4430
- data/include/rice/stl.hpp +769 -222
- data/lib/mkmf-rice.rb +37 -95
- data/rice/Address_Registration_Guard.hpp +72 -3
- data/rice/Arg.hpp +19 -5
- data/rice/Arg.ipp +24 -0
- data/rice/Callback.hpp +21 -0
- data/rice/Callback.ipp +13 -0
- data/rice/Constructor.hpp +4 -27
- data/rice/Constructor.ipp +79 -0
- data/rice/Data_Object.hpp +74 -3
- data/rice/Data_Object.ipp +324 -32
- data/rice/Data_Type.hpp +215 -3
- data/rice/Data_Type.ipp +125 -64
- data/rice/Director.hpp +0 -2
- data/rice/Enum.hpp +4 -6
- data/rice/Enum.ipp +101 -57
- data/rice/Exception.hpp +62 -2
- data/rice/Exception.ipp +7 -12
- data/rice/JumpException.hpp +44 -0
- data/rice/JumpException.ipp +48 -0
- data/rice/MemoryView.hpp +11 -0
- data/rice/MemoryView.ipp +43 -0
- data/rice/Return.hpp +6 -26
- data/rice/Return.ipp +10 -16
- data/rice/detail/DefaultHandler.hpp +12 -0
- data/rice/detail/DefaultHandler.ipp +8 -0
- data/rice/detail/HandlerRegistry.hpp +5 -35
- data/rice/detail/HandlerRegistry.ipp +7 -11
- data/rice/detail/InstanceRegistry.hpp +1 -4
- data/rice/detail/MethodInfo.hpp +15 -5
- data/rice/detail/MethodInfo.ipp +78 -6
- data/rice/detail/Native.hpp +32 -0
- data/rice/detail/Native.ipp +129 -0
- data/rice/detail/NativeAttributeGet.hpp +51 -0
- data/rice/detail/NativeAttributeGet.ipp +51 -0
- data/rice/detail/NativeAttributeSet.hpp +43 -0
- data/rice/detail/NativeAttributeSet.ipp +82 -0
- data/rice/detail/NativeCallbackFFI.hpp +55 -0
- data/rice/detail/NativeCallbackFFI.ipp +151 -0
- data/rice/detail/NativeCallbackSimple.hpp +30 -0
- data/rice/detail/NativeCallbackSimple.ipp +29 -0
- data/rice/detail/NativeFunction.hpp +20 -21
- data/rice/detail/NativeFunction.ipp +199 -64
- data/rice/detail/NativeIterator.hpp +8 -11
- data/rice/detail/NativeIterator.ipp +27 -31
- data/rice/detail/NativeRegistry.hpp +24 -15
- data/rice/detail/NativeRegistry.ipp +23 -48
- data/rice/detail/Proc.hpp +4 -0
- data/rice/detail/Proc.ipp +85 -0
- data/rice/detail/Registries.hpp +0 -7
- data/rice/detail/Registries.ipp +0 -18
- data/rice/detail/RubyFunction.hpp +0 -3
- data/rice/detail/RubyFunction.ipp +4 -8
- data/rice/detail/RubyType.hpp +19 -0
- data/rice/detail/RubyType.ipp +187 -0
- data/rice/detail/TupleIterator.hpp +14 -0
- data/rice/detail/Type.hpp +5 -6
- data/rice/detail/Type.ipp +150 -33
- data/rice/detail/TypeRegistry.hpp +15 -7
- data/rice/detail/TypeRegistry.ipp +105 -12
- data/rice/detail/Wrapper.hpp +6 -5
- data/rice/detail/Wrapper.ipp +45 -23
- data/rice/detail/cpp_protect.hpp +5 -6
- data/rice/detail/default_allocation_func.ipp +0 -2
- data/rice/detail/from_ruby.hpp +37 -3
- data/rice/detail/from_ruby.ipp +911 -454
- data/rice/detail/ruby.hpp +18 -0
- data/rice/detail/to_ruby.hpp +41 -3
- data/rice/detail/to_ruby.ipp +437 -113
- data/rice/global_function.hpp +0 -4
- data/rice/global_function.ipp +1 -2
- data/rice/rice.hpp +105 -22
- data/rice/ruby_mark.hpp +4 -3
- data/rice/stl.hpp +4 -0
- data/test/embed_ruby.cpp +4 -1
- data/test/extconf.rb +2 -0
- data/test/ruby/test_multiple_extensions_same_class.rb +14 -14
- data/test/test_Address_Registration_Guard.cpp +5 -0
- data/test/test_Array.cpp +12 -1
- data/test/test_Attribute.cpp +103 -21
- data/test/test_Builtin_Object.cpp +5 -0
- data/test/test_Callback.cpp +231 -0
- data/test/test_Class.cpp +5 -31
- data/test/test_Constructor.cpp +69 -6
- data/test/test_Data_Object.cpp +9 -4
- data/test/test_Data_Type.cpp +428 -64
- data/test/test_Director.cpp +10 -5
- data/test/test_Enum.cpp +152 -40
- data/test/test_Exception.cpp +235 -0
- data/test/test_File.cpp +70 -0
- data/test/test_From_Ruby.cpp +542 -0
- data/test/test_Hash.cpp +5 -0
- data/test/test_Identifier.cpp +5 -0
- data/test/test_Inheritance.cpp +6 -1
- data/test/test_Iterator.cpp +5 -0
- data/test/test_JumpException.cpp +22 -0
- data/test/test_Keep_Alive.cpp +6 -1
- data/test/test_Keep_Alive_No_Wrapper.cpp +5 -0
- data/test/test_Memory_Management.cpp +5 -0
- data/test/test_Module.cpp +118 -64
- data/test/test_Native_Registry.cpp +2 -33
- data/test/test_Object.cpp +5 -0
- data/test/test_Overloads.cpp +631 -0
- data/test/test_Ownership.cpp +67 -4
- data/test/test_Proc.cpp +45 -0
- data/test/test_Self.cpp +5 -0
- data/test/test_Stl_Exception.cpp +109 -0
- data/test/test_Stl_Map.cpp +22 -8
- data/test/test_Stl_Optional.cpp +5 -0
- data/test/test_Stl_Pair.cpp +7 -2
- data/test/test_Stl_Reference_Wrapper.cpp +5 -0
- data/test/test_Stl_SmartPointer.cpp +210 -5
- data/test/test_Stl_String.cpp +5 -0
- data/test/test_Stl_String_View.cpp +5 -0
- data/test/test_Stl_Type.cpp +147 -0
- data/test/test_Stl_Unordered_Map.cpp +18 -7
- data/test/test_Stl_Variant.cpp +5 -0
- data/test/test_Stl_Vector.cpp +130 -8
- data/test/test_String.cpp +5 -0
- data/test/test_Struct.cpp +5 -0
- data/test/test_Symbol.cpp +5 -0
- data/test/test_Template.cpp +192 -0
- data/test/test_To_Ruby.cpp +152 -0
- data/test/test_Tracking.cpp +1 -0
- data/test/test_Type.cpp +100 -0
- data/test/test_global_functions.cpp +53 -6
- data/test/unittest.cpp +8 -0
- metadata +37 -20
- data/lib/version.rb +0 -3
- data/rice/Address_Registration_Guard_defn.hpp +0 -79
- data/rice/Data_Object_defn.hpp +0 -84
- data/rice/Data_Type_defn.hpp +0 -190
- data/rice/Exception_defn.hpp +0 -68
- data/rice/HandlerRegistration.hpp +0 -15
- data/rice/Identifier.hpp +0 -50
- data/rice/Identifier.ipp +0 -29
- data/rice/detail/ExceptionHandler.hpp +0 -8
- data/rice/detail/ExceptionHandler.ipp +0 -28
- data/rice/detail/ExceptionHandler_defn.hpp +0 -77
- data/rice/detail/Jump_Tag.hpp +0 -21
- data/rice/detail/NativeAttribute.hpp +0 -64
- data/rice/detail/NativeAttribute.ipp +0 -112
- data/rice/detail/from_ruby_defn.hpp +0 -38
- data/rice/detail/to_ruby_defn.hpp +0 -48
- data/test/test_Jump_Tag.cpp +0 -17
- data/test/test_To_From_Ruby.cpp +0 -399
data/rice/Data_Type.ipp
CHANGED
@@ -1,24 +1,9 @@
|
|
1
|
-
#ifndef Rice__Data_Type__ipp_
|
2
|
-
#define Rice__Data_Type__ipp_
|
3
|
-
|
4
|
-
#include "traits/attribute_traits.hpp"
|
5
|
-
#include "traits/method_traits.hpp"
|
6
|
-
#include "detail/NativeRegistry.hpp"
|
7
|
-
#include "detail/NativeAttribute.hpp"
|
8
|
-
#include "detail/default_allocation_func.hpp"
|
9
|
-
#include "detail/TypeRegistry.hpp"
|
10
|
-
#include "detail/Wrapper.hpp"
|
11
|
-
#include "detail/NativeIterator.hpp"
|
12
|
-
#include "cpp_api/Class.hpp"
|
13
|
-
#include "cpp_api/String.hpp"
|
14
|
-
#include "ruby_mark.hpp"
|
15
|
-
|
16
1
|
#include <stdexcept>
|
17
2
|
|
18
3
|
namespace Rice
|
19
4
|
{
|
20
5
|
template<typename T>
|
21
|
-
void ruby_mark_internal(detail::Wrapper* wrapper)
|
6
|
+
inline void ruby_mark_internal(detail::Wrapper* wrapper)
|
22
7
|
{
|
23
8
|
// Tell the wrapper to mark the objects its keeping alive
|
24
9
|
wrapper->ruby_mark();
|
@@ -29,17 +14,23 @@ namespace Rice
|
|
29
14
|
}
|
30
15
|
|
31
16
|
template<typename T>
|
32
|
-
void ruby_free_internal(detail::Wrapper* wrapper)
|
17
|
+
inline void ruby_free_internal(detail::Wrapper* wrapper)
|
33
18
|
{
|
34
19
|
delete wrapper;
|
35
20
|
}
|
36
21
|
|
37
22
|
template<typename T>
|
38
|
-
size_t ruby_size_internal(const T* data)
|
23
|
+
inline size_t ruby_size_internal(const T* data)
|
39
24
|
{
|
40
25
|
return sizeof(T);
|
41
26
|
}
|
42
27
|
|
28
|
+
template<>
|
29
|
+
inline size_t ruby_size_internal(const void* data)
|
30
|
+
{
|
31
|
+
return sizeof(void*);
|
32
|
+
}
|
33
|
+
|
43
34
|
template<typename T>
|
44
35
|
template <typename Base_T>
|
45
36
|
inline Data_Type<T> Data_Type<T>::bind(const Module& klass)
|
@@ -68,12 +59,11 @@ namespace Rice
|
|
68
59
|
// Now register with the type registry
|
69
60
|
detail::Registries::instance.types.add<T>(klass_, rb_data_type_);
|
70
61
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
(*it)->set_value(klass);
|
62
|
+
auto iter = Data_Type<T>::unbound_instances_.begin();
|
63
|
+
while (iter != Data_Type<T>::unbound_instances_.end())
|
64
|
+
{
|
65
|
+
(*iter)->set_value(klass);
|
66
|
+
iter = Data_Type<T>::unbound_instances_.erase(iter);
|
77
67
|
}
|
78
68
|
|
79
69
|
return Data_Type<T>();
|
@@ -99,7 +89,7 @@ namespace Rice
|
|
99
89
|
{
|
100
90
|
if (!is_bound())
|
101
91
|
{
|
102
|
-
|
92
|
+
this->unbound_instances_.insert(this);
|
103
93
|
}
|
104
94
|
}
|
105
95
|
|
@@ -109,12 +99,6 @@ namespace Rice
|
|
109
99
|
this->bind(klass);
|
110
100
|
}
|
111
101
|
|
112
|
-
template<typename T>
|
113
|
-
inline Data_Type<T>::~Data_Type()
|
114
|
-
{
|
115
|
-
unbound_instances().erase(this);
|
116
|
-
}
|
117
|
-
|
118
102
|
template<typename T>
|
119
103
|
inline rb_data_type_t* Data_Type<T>::ruby_data_type()
|
120
104
|
{
|
@@ -137,17 +121,50 @@ namespace Rice
|
|
137
121
|
}
|
138
122
|
|
139
123
|
template<typename T>
|
140
|
-
template<typename Constructor_T, typename...
|
141
|
-
inline Data_Type<T>& Data_Type<T>::define_constructor(Constructor_T constructor,
|
124
|
+
template<typename Constructor_T, typename...Rice_Arg_Ts>
|
125
|
+
inline Data_Type<T>& Data_Type<T>::define_constructor(Constructor_T constructor, Rice_Arg_Ts const& ...args)
|
142
126
|
{
|
143
127
|
check_is_bound();
|
144
128
|
|
145
129
|
// Define a Ruby allocator which creates the Ruby object
|
146
130
|
detail::protect(rb_define_alloc_func, static_cast<VALUE>(*this), detail::default_allocation_func<T>);
|
147
131
|
|
148
|
-
//
|
149
|
-
|
132
|
+
// We can't do anything with move constructors so blow up
|
133
|
+
static_assert(!Constructor_T::isMoveConstructor(), "Rice does not support move constructors");
|
134
|
+
|
135
|
+
// If this is a copy constructor then use it to support Ruby's Object#dup and Object#clone methods.
|
136
|
+
// Otherwise if a user calls #dup or #clone an error will occur because the newly cloned Ruby
|
137
|
+
// object will have a NULL ptr because the C++ object is never copied. This also prevents having
|
138
|
+
// very unlike Ruby code of:
|
139
|
+
//
|
140
|
+
// my_object_copy = MyObject.new(my_ojbect_original).
|
141
|
+
|
142
|
+
if constexpr (Constructor_T::isCopyConstructor())
|
143
|
+
{
|
144
|
+
// Define initialize_copy that will copy the C++ object
|
145
|
+
this->define_method("initialize_copy", &Constructor_T::initialize_copy, args...);
|
146
|
+
}
|
147
|
+
else if constexpr (Constructor_T::isMoveConstructor())
|
148
|
+
{
|
149
|
+
throw std::runtime_error("Rice does not support move constructors");
|
150
|
+
}
|
151
|
+
else
|
152
|
+
{
|
153
|
+
// Define an initialize function that will create the C++ object
|
154
|
+
this->define_method("initialize", &Constructor_T::initialize, args...);
|
155
|
+
}
|
156
|
+
|
157
|
+
return *this;
|
158
|
+
}
|
150
159
|
|
160
|
+
template<typename T>
|
161
|
+
template<typename Function_T>
|
162
|
+
inline Data_Type<T>& Data_Type<T>::define(Function_T func)
|
163
|
+
{
|
164
|
+
// The passed in this pointer is an RValue, so we need to keep it alive by
|
165
|
+
// assigning it to a const lvalue
|
166
|
+
const auto& dummy = *this;
|
167
|
+
func(*this);
|
151
168
|
return *this;
|
152
169
|
}
|
153
170
|
|
@@ -184,56 +201,84 @@ namespace Rice
|
|
184
201
|
{
|
185
202
|
if (!is_bound())
|
186
203
|
{
|
187
|
-
std::string message = "Type " + detail::typeName(typeid(T))
|
188
|
-
throw std::
|
204
|
+
std::string message = "Type is not defined with Rice: " + detail::typeName(typeid(T));
|
205
|
+
throw std::invalid_argument(message.c_str());
|
189
206
|
}
|
190
207
|
}
|
191
208
|
|
192
|
-
template<typename T
|
193
|
-
inline Data_Type<T
|
209
|
+
template<typename T>
|
210
|
+
inline bool Data_Type<T>::is_defined(Object parent, const std::string& name)
|
194
211
|
{
|
212
|
+
// Is the class already defined?
|
195
213
|
if (detail::Registries::instance.types.isDefined<T>())
|
196
214
|
{
|
197
|
-
|
215
|
+
Data_Type<T> result = Data_Type<T>();
|
216
|
+
|
217
|
+
// If this redefinition is a different name then create a new constant
|
218
|
+
if (result.name() != name)
|
219
|
+
{
|
220
|
+
detail::protect(rb_define_const, parent, name.c_str(), result.klass());
|
221
|
+
}
|
222
|
+
|
223
|
+
return true;
|
198
224
|
}
|
199
|
-
|
200
|
-
|
225
|
+
return false;
|
226
|
+
}
|
227
|
+
|
228
|
+
template<typename Base_T>
|
229
|
+
inline Class get_superklass()
|
230
|
+
{
|
231
|
+
Class result;
|
201
232
|
|
202
233
|
if constexpr (std::is_void_v<Base_T>)
|
203
234
|
{
|
204
|
-
|
235
|
+
result = rb_cObject;
|
205
236
|
}
|
206
237
|
else
|
207
238
|
{
|
208
|
-
|
239
|
+
// This gives a chance for to auto-register classes such as std::exception
|
240
|
+
detail::verifyType<Base_T>();
|
241
|
+
result = Data_Type<Base_T>::klass();
|
209
242
|
}
|
210
|
-
|
211
|
-
|
212
|
-
c.undef_creation_funcs();
|
213
|
-
return Data_Type<T>::template bind<Base_T>(c);
|
243
|
+
|
244
|
+
return result;
|
214
245
|
}
|
215
246
|
|
216
247
|
template<typename T, typename Base_T>
|
217
|
-
inline Data_Type<T>
|
248
|
+
inline Data_Type<T> define_class_under(Object parent, Identifier id, Class superKlass)
|
218
249
|
{
|
219
|
-
if (
|
250
|
+
if (Rice::Data_Type<T>::is_defined(parent, id.str()))
|
220
251
|
{
|
221
252
|
return Data_Type<T>();
|
222
253
|
}
|
223
254
|
|
224
|
-
Class superKlass;
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
255
|
+
Class klass = define_class_under(parent, id, superKlass);
|
256
|
+
klass.undef_creation_funcs();
|
257
|
+
return Data_Type<T>::template bind<Base_T>(klass);
|
258
|
+
}
|
259
|
+
|
260
|
+
template<typename T, typename Base_T>
|
261
|
+
inline Data_Type<T> define_class_under(Object parent, char const* name)
|
262
|
+
{
|
263
|
+
Identifier id(name);
|
264
|
+
Class superKlass = get_superklass<Base_T>();
|
265
|
+
return define_class_under<T, Base_T>(parent, id, superKlass);
|
266
|
+
}
|
267
|
+
|
268
|
+
template<typename T, typename Base_T>
|
269
|
+
inline Data_Type<T> define_class(char const* name)
|
270
|
+
{
|
271
|
+
std::string klassName(name);
|
272
|
+
|
273
|
+
if (Rice::Data_Type<T>::is_defined(rb_cObject, klassName))
|
230
274
|
{
|
231
|
-
|
275
|
+
return Data_Type<T>();
|
232
276
|
}
|
233
277
|
|
234
|
-
Class
|
235
|
-
|
236
|
-
|
278
|
+
Class superKlass = get_superklass<Base_T>();
|
279
|
+
Class klass = define_class(name, superKlass);
|
280
|
+
klass.undef_creation_funcs();
|
281
|
+
return Data_Type<T>::template bind<Base_T>(klass);
|
237
282
|
}
|
238
283
|
|
239
284
|
template<typename T>
|
@@ -256,8 +301,18 @@ namespace Rice
|
|
256
301
|
// Make sure the Attribute type has been previously seen by Rice
|
257
302
|
detail::verifyType<typename detail::attribute_traits<Attribute_T>::attr_type>();
|
258
303
|
|
259
|
-
// Define native attribute
|
260
|
-
|
304
|
+
// Define native attribute getter
|
305
|
+
if (access == AttrAccess::ReadWrite || access == AttrAccess::Read)
|
306
|
+
detail::NativeAttributeGet<Attribute_T>::define(klass_, name, std::forward<Attribute_T>(attribute));
|
307
|
+
|
308
|
+
using Attr_T = typename detail::NativeAttributeSet<Attribute_T>::Attr_T;
|
309
|
+
if constexpr (!std::is_const_v<Attr_T> &&
|
310
|
+
(std::is_fundamental_v<Attr_T> || std::is_assignable_v<Attr_T, Attr_T>))
|
311
|
+
{
|
312
|
+
// Define native attribute setter
|
313
|
+
if (access == AttrAccess::ReadWrite || access == AttrAccess::Write)
|
314
|
+
detail::NativeAttributeSet<Attribute_T>::define(klass_, name, std::forward<Attribute_T>(attribute));
|
315
|
+
}
|
261
316
|
|
262
317
|
return *this;
|
263
318
|
}
|
@@ -271,7 +326,14 @@ namespace Rice
|
|
271
326
|
|
272
327
|
// Define native attribute
|
273
328
|
VALUE singleton = detail::protect(rb_singleton_class, this->value());
|
274
|
-
|
329
|
+
|
330
|
+
// Define native attribute getter
|
331
|
+
if (access == AttrAccess::ReadWrite || access == AttrAccess::Read)
|
332
|
+
detail::NativeAttributeGet<Attribute_T>::define(singleton, name, std::forward<Attribute_T>(attribute));
|
333
|
+
|
334
|
+
// Define native attribute setter
|
335
|
+
if (access == AttrAccess::ReadWrite || access == AttrAccess::Write)
|
336
|
+
detail::NativeAttributeSet<Attribute_T>::define(singleton, name, std::forward<Attribute_T>(attribute));
|
275
337
|
|
276
338
|
return *this;
|
277
339
|
}
|
@@ -289,4 +351,3 @@ namespace Rice
|
|
289
351
|
detail::NativeFunction<T, Function_T, IsMethod>::define(klass, name, std::forward<Function_T>(function), methodInfo);
|
290
352
|
}
|
291
353
|
}
|
292
|
-
#endif
|
data/rice/Director.hpp
CHANGED
data/rice/Enum.hpp
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
#ifndef Rice__Enum__hpp_
|
2
2
|
#define Rice__Enum__hpp_
|
3
3
|
|
4
|
-
#include "Data_Type.hpp"
|
5
|
-
#include <map>
|
6
|
-
|
7
4
|
namespace Rice
|
8
5
|
{
|
9
6
|
/*!
|
@@ -59,9 +56,10 @@ namespace Rice
|
|
59
56
|
};
|
60
57
|
|
61
58
|
template<typename T>
|
62
|
-
Enum<T> define_enum(char const* name
|
63
|
-
} // namespace Rice
|
59
|
+
Enum<T> define_enum(char const* name);
|
64
60
|
|
65
|
-
|
61
|
+
template<typename T>
|
62
|
+
Enum<T> define_enum_under(char const* name, Module module );
|
63
|
+
} // namespace Rice
|
66
64
|
|
67
65
|
#endif // Rice__Enum__hpp_
|
data/rice/Enum.ipp
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
#include "detail/TypeRegistry.hpp"
|
2
|
-
#include "Data_Object.hpp"
|
3
|
-
#include "cpp_api/String.hpp"
|
4
1
|
|
5
2
|
#include <stdexcept>
|
6
3
|
|
@@ -32,57 +29,68 @@ namespace Rice
|
|
32
29
|
// First we need a constructor
|
33
30
|
klass.define_constructor(Constructor<Enum_T>());
|
34
31
|
|
35
|
-
// Instance methods
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
.define_method("
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
32
|
+
// Instance methods. The self parameter is confusing because it is really a Data_Object<Enum_T>.
|
33
|
+
// However, if we make that the type then the From_Ruby code will consider it a
|
34
|
+
// Data_Type<Data_Object<Enum_T>>>. But in define class above it was actually bound as
|
35
|
+
// Data_Type<Enum_T>. Thus the static_casts in the methods below.
|
36
|
+
klass.define_method("to_s", [](Enum_T& notSelf)
|
37
|
+
{
|
38
|
+
// We have to return string because we don't know if std::string support has
|
39
|
+
// been included by the user
|
40
|
+
Data_Object<Enum_T> self = static_cast<Data_Object<Enum_T>>(notSelf);
|
41
|
+
return String(valuesToNames_[*self]);
|
42
|
+
})
|
43
|
+
.define_method("to_int", [](Enum_T& notSelf) -> Underlying_T
|
44
|
+
{
|
45
|
+
Data_Object<Enum_T> self = static_cast<Data_Object<Enum_T>>(notSelf);
|
46
|
+
return static_cast<Underlying_T>(*self);
|
47
|
+
})
|
48
|
+
.define_method("inspect", [](Enum_T& notSelf)
|
49
|
+
{
|
50
|
+
Data_Object<Enum_T> self = static_cast<Data_Object<Enum_T>>(notSelf);
|
51
|
+
|
52
|
+
std::stringstream result;
|
53
|
+
VALUE rubyKlass = Enum<Enum_T>::klass().value();
|
54
|
+
result << "#<" << detail::protect(rb_class2name, rubyKlass)
|
55
|
+
<< "::" << Enum<Enum_T>::valuesToNames_[*self] << ">";
|
56
|
+
|
57
|
+
// We have to return string because we don't know if std::string support has
|
58
|
+
// been included by the user
|
59
|
+
return String(result.str());
|
60
|
+
})
|
61
|
+
.define_method("hash", [](Enum_T& notSelf) -> Underlying_T
|
62
|
+
{
|
63
|
+
Data_Object<Enum_T> self = static_cast<Data_Object<Enum_T>>(notSelf);
|
64
|
+
return (Underlying_T)*self;
|
65
|
+
})
|
66
|
+
.define_method("eql?", [](Enum_T& notSelf, Enum_T& notOther)
|
67
|
+
{
|
68
|
+
Data_Object<Enum_T> self = static_cast<Data_Object<Enum_T>>(notSelf);
|
69
|
+
Data_Object<Enum_T> other = static_cast<Data_Object<Enum_T>>(notOther);
|
70
|
+
return self == other;
|
71
|
+
});
|
65
72
|
|
66
73
|
// Add aliases
|
67
74
|
rb_define_alias(klass, "===", "eql?");
|
75
|
+
rb_define_alias(klass, "to_i", "to_int");
|
68
76
|
|
69
77
|
// Add comparable support
|
70
78
|
klass.include_module(rb_mComparable)
|
71
79
|
.define_method("<=>", [](Enum_T& self, Enum_T& other)
|
72
|
-
{
|
73
|
-
if (self == other)
|
74
|
-
{
|
75
|
-
return 0;
|
76
|
-
}
|
77
|
-
else if (self < other)
|
78
80
|
{
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
81
|
+
if (self == other)
|
82
|
+
{
|
83
|
+
return 0;
|
84
|
+
}
|
85
|
+
else if (self < other)
|
86
|
+
{
|
87
|
+
return -1;
|
88
|
+
}
|
89
|
+
else
|
90
|
+
{
|
91
|
+
return 1;
|
92
|
+
}
|
93
|
+
});
|
86
94
|
|
87
95
|
// Add enumerable support
|
88
96
|
klass.include_module(rb_mEnumerable)
|
@@ -91,7 +99,7 @@ namespace Rice
|
|
91
99
|
if (!rb_block_given_p())
|
92
100
|
{
|
93
101
|
return rb_enumeratorize_with_size(ruby_klass, Identifier("each").to_sym(),
|
94
|
-
|
102
|
+
0, nullptr, 0);
|
95
103
|
}
|
96
104
|
|
97
105
|
for (auto& pair : valuesToNames_)
|
@@ -102,22 +110,58 @@ namespace Rice
|
|
102
110
|
}
|
103
111
|
|
104
112
|
return ruby_klass;
|
105
|
-
|
106
|
-
|
113
|
+
}, Return().setValue());
|
114
|
+
|
115
|
+
// Add bitwise operators
|
116
|
+
klass.define_method("&", [](Enum_T& self, Enum_T& other) -> Underlying_T
|
107
117
|
{
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
118
|
+
return (Underlying_T)self & (Underlying_T)other;
|
119
|
+
})
|
120
|
+
.define_method("|", [](Enum_T& self, Enum_T& other) -> Underlying_T
|
121
|
+
{
|
122
|
+
return (Underlying_T)self | (Underlying_T)other;
|
123
|
+
})
|
124
|
+
.define_method("^", [](Enum_T& self, Enum_T& other) -> Underlying_T
|
125
|
+
{
|
126
|
+
return (Underlying_T)self ^ (Underlying_T)other;
|
127
|
+
})
|
128
|
+
.define_method("~", [](Enum_T& self) -> Underlying_T
|
129
|
+
{
|
130
|
+
return ~(Underlying_T)self;
|
131
|
+
});
|
132
|
+
|
133
|
+
// Add shift operators
|
134
|
+
klass.define_method("<<", [](Enum_T& self, int shift) -> Underlying_T
|
135
|
+
{
|
136
|
+
return (Underlying_T)self << shift;
|
137
|
+
})
|
138
|
+
.define_method(">>", [](Enum_T& self, int shift) -> Underlying_T
|
139
|
+
{
|
140
|
+
return (Underlying_T)self >> shift;
|
141
|
+
});
|
142
|
+
|
143
|
+
// Add conversions from int
|
144
|
+
klass.define_singleton_method("from_int", [](VALUE ruby_klass, int32_t value) -> Object
|
145
|
+
{
|
146
|
+
auto iter = Enum<Enum_T>::valuesToNames_.find((Enum_T)value);
|
147
|
+
if (iter == Enum<Enum_T>::valuesToNames_.end())
|
148
|
+
{
|
149
|
+
throw std::runtime_error("Unknown enum value: " + std::to_string(value));
|
150
|
+
}
|
113
151
|
|
114
|
-
|
115
|
-
|
152
|
+
std::string name = iter->second;
|
153
|
+
return Object(ruby_klass).const_get(name);
|
116
154
|
});
|
117
155
|
}
|
118
156
|
|
119
157
|
template<typename Enum_T>
|
120
|
-
Enum<Enum_T> define_enum(char const* name
|
158
|
+
Enum<Enum_T> define_enum(char const* name)
|
159
|
+
{
|
160
|
+
return define_enum_under<Enum_T>(name, rb_cObject);
|
161
|
+
}
|
162
|
+
|
163
|
+
template<typename Enum_T>
|
164
|
+
Enum<Enum_T> define_enum_under(char const* name, Module module)
|
121
165
|
{
|
122
166
|
if (detail::Registries::instance.types.isDefined<Enum_T>())
|
123
167
|
{
|
data/rice/Exception.hpp
CHANGED
@@ -1,7 +1,67 @@
|
|
1
1
|
#ifndef Rice__Exception__hpp_
|
2
2
|
#define Rice__Exception__hpp_
|
3
3
|
|
4
|
-
#include
|
5
|
-
|
4
|
+
#include <stdexcept>
|
5
|
+
|
6
|
+
namespace Rice
|
7
|
+
{
|
8
|
+
//! A placeholder for Ruby exceptions.
|
9
|
+
/*! You can use this to safely throw a Ruby exception using C++ syntax:
|
10
|
+
* \code
|
11
|
+
* VALUE foo(VALUE self) {
|
12
|
+
* RUBY_TRY {
|
13
|
+
* throw Rice::Exception(rb_eMyException, "uh oh!");
|
14
|
+
* RUBY_CATCH
|
15
|
+
* }
|
16
|
+
* \endcode
|
17
|
+
*/
|
18
|
+
class Exception
|
19
|
+
: public std::exception
|
20
|
+
{
|
21
|
+
public:
|
22
|
+
//! Construct a Exception with a Ruby exception instance
|
23
|
+
explicit Exception(VALUE exception);
|
24
|
+
|
25
|
+
//! Construct a Exception with printf-style formatting.
|
26
|
+
/*! \param exc either an exception object or a class that inherits
|
27
|
+
* from Exception.
|
28
|
+
* \param fmt a printf-style format string
|
29
|
+
* \param ... the arguments to the format string.
|
30
|
+
*/
|
31
|
+
template <typename... Arg_Ts>
|
32
|
+
Exception(const Exception& other, char const* fmt, Arg_Ts&&...args);
|
33
|
+
|
34
|
+
//! Construct a Exception with printf-style formatting.
|
35
|
+
/*! \param exc either an exception object or a class that inherits
|
36
|
+
* from Exception.
|
37
|
+
* \param fmt a printf-style format string
|
38
|
+
* \param ... the arguments to the format string.
|
39
|
+
*/
|
40
|
+
template <typename... Arg_Ts>
|
41
|
+
Exception(const VALUE exceptionType, char const* fmt, Arg_Ts&&...args);
|
42
|
+
|
43
|
+
//! Destructor
|
44
|
+
virtual ~Exception() noexcept = default;
|
45
|
+
|
46
|
+
//! Get message as a char const *.
|
47
|
+
/*! If message is a non-string object, then this function will attempt
|
48
|
+
* to throw an exception (which it can't do because of the no-throw
|
49
|
+
* specification).
|
50
|
+
* \return the underlying C pointer of the underlying message object.
|
51
|
+
*/
|
52
|
+
virtual char const* what() const noexcept override;
|
53
|
+
|
54
|
+
//! Returns the Ruby exception class
|
55
|
+
VALUE class_of() const;
|
56
|
+
|
57
|
+
//! Returns an instance of a Ruby exception
|
58
|
+
VALUE value() const;
|
59
|
+
|
60
|
+
private:
|
61
|
+
// TODO: Do we need to tell the Ruby gc about an exception instance?
|
62
|
+
mutable VALUE exception_ = Qnil;
|
63
|
+
mutable std::string message_;
|
64
|
+
};
|
65
|
+
} // namespace Rice
|
6
66
|
|
7
67
|
#endif // Rice__Exception__hpp_
|
data/rice/Exception.ipp
CHANGED
@@ -1,7 +1,3 @@
|
|
1
|
-
#ifndef Rice__Exception__ipp_
|
2
|
-
#define Rice__Exception__ipp_
|
3
|
-
|
4
|
-
#include "detail/from_ruby.hpp"
|
5
1
|
|
6
2
|
namespace Rice
|
7
3
|
{
|
@@ -18,10 +14,10 @@ namespace Rice
|
|
18
14
|
template <typename... Arg_Ts>
|
19
15
|
inline Exception::Exception(const VALUE exceptionClass, char const* fmt, Arg_Ts&&...args)
|
20
16
|
{
|
21
|
-
#
|
22
|
-
#pragma GCC diagnostic push
|
23
|
-
#pragma GCC diagnostic ignored "-Wformat-security"
|
24
|
-
#endif
|
17
|
+
#if defined(__GNUC__) || defined(__clang__)
|
18
|
+
#pragma GCC diagnostic push
|
19
|
+
#pragma GCC diagnostic ignored "-Wformat-security"
|
20
|
+
#endif
|
25
21
|
|
26
22
|
size_t size = std::snprintf(nullptr, 0, fmt, std::forward<Arg_Ts>(args)...);
|
27
23
|
this->message_ = std::string(size, '\0');
|
@@ -31,9 +27,9 @@ namespace Rice
|
|
31
27
|
// will add a null character internally at n + 1
|
32
28
|
std::snprintf(&this->message_[0], size + 1, fmt, std::forward<Arg_Ts>(args)...);
|
33
29
|
|
34
|
-
#
|
35
|
-
#pragma GCC diagnostic pop
|
36
|
-
#endif
|
30
|
+
#if defined(__GNUC__) || defined(__clang__)
|
31
|
+
#pragma GCC diagnostic pop
|
32
|
+
#endif
|
37
33
|
|
38
34
|
// Now create the Ruby exception
|
39
35
|
this->exception_ = detail::protect(rb_exc_new2, exceptionClass, this->message_.c_str());
|
@@ -61,4 +57,3 @@ namespace Rice
|
|
61
57
|
return this->exception_;
|
62
58
|
}
|
63
59
|
}
|
64
|
-
#endif // Rice__Exception__ipp_
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#ifndef Rice__JumpException__hpp_
|
2
|
+
#define Rice__JumpException__hpp_
|
3
|
+
|
4
|
+
namespace Rice
|
5
|
+
{
|
6
|
+
//! A placeholder for Ruby longjmp data.
|
7
|
+
/*! When a Ruby exception is caught, the tag used for the longjmp is stored in
|
8
|
+
* a Jump_Tag, then later passed to rb_jump_tag() when there is no more
|
9
|
+
* C++ code to pass over.
|
10
|
+
*/
|
11
|
+
class JumpException : public std::exception
|
12
|
+
{
|
13
|
+
public:
|
14
|
+
// Copied from vm_core.h
|
15
|
+
enum ruby_tag_type {
|
16
|
+
RUBY_TAG_NONE = 0x0,
|
17
|
+
RUBY_TAG_RETURN = 0x1,
|
18
|
+
RUBY_TAG_BREAK = 0x2,
|
19
|
+
RUBY_TAG_NEXT = 0x3,
|
20
|
+
RUBY_TAG_RETRY = 0x4,
|
21
|
+
RUBY_TAG_REDO = 0x5,
|
22
|
+
RUBY_TAG_RAISE = 0x6,
|
23
|
+
RUBY_TAG_THROW = 0x7,
|
24
|
+
RUBY_TAG_FATAL = 0x8,
|
25
|
+
RUBY_TAG_MASK = 0xf
|
26
|
+
};
|
27
|
+
|
28
|
+
public:
|
29
|
+
JumpException(ruby_tag_type tag);
|
30
|
+
virtual const char* what() const noexcept override;
|
31
|
+
|
32
|
+
public:
|
33
|
+
//! The tag being held.
|
34
|
+
ruby_tag_type tag;
|
35
|
+
|
36
|
+
private:
|
37
|
+
void createMessage();
|
38
|
+
|
39
|
+
private:
|
40
|
+
std::string message_;
|
41
|
+
};
|
42
|
+
} // namespace Rice
|
43
|
+
|
44
|
+
#endif // Rice__JumpException__hpp_
|