rice 4.3.3 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/detail/Type.ipp
CHANGED
@@ -1,12 +1,3 @@
|
|
1
|
-
#include "../traits/rice_traits.hpp"
|
2
|
-
|
3
|
-
#include <iosfwd>
|
4
|
-
#include <iterator>
|
5
|
-
#include <numeric>
|
6
|
-
#include <regex>
|
7
|
-
#include <sstream>
|
8
|
-
#include <tuple>
|
9
|
-
|
10
1
|
#ifdef __GNUC__
|
11
2
|
#include <cxxabi.h>
|
12
3
|
#include <cstdlib>
|
@@ -15,6 +6,19 @@
|
|
15
6
|
|
16
7
|
namespace Rice::detail
|
17
8
|
{
|
9
|
+
template<typename T>
|
10
|
+
bool Type<T>::verify()
|
11
|
+
{
|
12
|
+
if constexpr (std::is_fundamental_v<T>)
|
13
|
+
{
|
14
|
+
return true;
|
15
|
+
}
|
16
|
+
else
|
17
|
+
{
|
18
|
+
return Registries::instance.types.verify<T>();
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
18
22
|
template<>
|
19
23
|
struct Type<void>
|
20
24
|
{
|
@@ -89,13 +93,76 @@ namespace Rice::detail
|
|
89
93
|
return demangle(typeInfo.name());
|
90
94
|
}
|
91
95
|
|
92
|
-
inline std::string
|
96
|
+
inline std::string typeName(const std::type_index& typeIndex)
|
97
|
+
{
|
98
|
+
return demangle(typeIndex.name());
|
99
|
+
}
|
100
|
+
|
101
|
+
// Find text inside of < > taking into account nested groups.
|
102
|
+
//
|
103
|
+
// Example:
|
104
|
+
//
|
105
|
+
// std::vector<std::vector<int>, std::allocator<std::vector, std::allocator<int>>>
|
106
|
+
inline std::string findGroup(std::string& string, size_t offset)
|
107
|
+
{
|
108
|
+
int depth = 0;
|
109
|
+
|
110
|
+
auto begin = string.begin() + offset;
|
111
|
+
auto start = begin;
|
112
|
+
for (auto iter = begin; iter != string.end(); iter++)
|
113
|
+
{
|
114
|
+
if (*iter == '<')
|
115
|
+
{
|
116
|
+
if (depth == 0)
|
117
|
+
{
|
118
|
+
start = iter;
|
119
|
+
}
|
120
|
+
depth++;
|
121
|
+
}
|
122
|
+
else if (*iter == '>')
|
123
|
+
{
|
124
|
+
depth--;
|
125
|
+
if (depth == 0)
|
126
|
+
{
|
127
|
+
// Add + 1 to include current ">" character
|
128
|
+
return string.substr(offset + (start - begin), 1 + (iter - start));
|
129
|
+
}
|
130
|
+
else if (depth < 0)
|
131
|
+
{
|
132
|
+
throw std::runtime_error("Unbalanced Group");
|
133
|
+
}
|
134
|
+
}
|
135
|
+
}
|
136
|
+
throw std::runtime_error("Unbalanced Group");
|
137
|
+
}
|
138
|
+
|
139
|
+
inline void replaceAll(std::string& string, std::regex regex, std::string replacement)
|
93
140
|
{
|
94
|
-
std::
|
141
|
+
std::smatch match;
|
142
|
+
while (std::regex_search(string, match, regex))
|
143
|
+
{
|
144
|
+
string = std::regex_replace(string, regex, replacement);
|
145
|
+
}
|
146
|
+
}
|
147
|
+
|
148
|
+
inline void removeGroup(std::string& string, std::regex regex)
|
149
|
+
{
|
150
|
+
std::smatch match;
|
151
|
+
while (std::regex_search(string, match, regex))
|
152
|
+
{
|
153
|
+
std::string group = findGroup(string, match.position());
|
154
|
+
group = match.str() + group;
|
155
|
+
string.erase(match.position(), group.length());
|
156
|
+
}
|
157
|
+
}
|
158
|
+
|
159
|
+
inline std::string makeClassName(const std::string& typeInfoName)
|
160
|
+
{
|
161
|
+
std::string base = typeInfoName;
|
95
162
|
|
96
163
|
// Remove class keyword
|
97
164
|
auto classRegex = std::regex("class +");
|
98
|
-
base = std::regex_replace(
|
165
|
+
base = std::regex_replace(typeInfoName, classRegex, "");
|
99
166
|
|
100
167
|
// Remove struct keyword
|
101
168
|
auto structRegex = std::regex("struct +");
|
@@ -109,31 +176,81 @@ namespace Rice::detail
|
|
109
176
|
auto stdRegex = std::regex("std::");
|
110
177
|
base = std::regex_replace(base, stdRegex, "");
|
111
178
|
|
112
|
-
// Replace
|
113
|
-
auto
|
114
|
-
|
179
|
+
// Replace basic_string with string
|
180
|
+
auto basicStringRegex = std::regex(R"(basic_string)");
|
181
|
+
replaceAll(base, basicStringRegex, "string");
|
182
|
+
|
183
|
+
// Remove allocators
|
184
|
+
std::regex allocatorRegex(R"(,\s*allocator)");
|
185
|
+
removeGroup(base, allocatorRegex);
|
115
186
|
|
116
|
-
//
|
117
|
-
|
118
|
-
|
187
|
+
// Remove char_traits
|
188
|
+
std::regex charTraitsRegex(R"(,\s*char_traits)");
|
189
|
+
removeGroup(base, charTraitsRegex);
|
119
190
|
|
120
|
-
//
|
121
|
-
|
122
|
-
|
191
|
+
// Remove less (std::map)
|
192
|
+
std::regex lessRegex(R"(,\s*less)");
|
193
|
+
removeGroup(base, lessRegex);
|
123
194
|
|
124
|
-
//
|
125
|
-
std::
|
126
|
-
|
127
|
-
std::istream_iterator<std::string>{} };
|
195
|
+
// Remove hash (std::unordered_map)
|
196
|
+
std::regex hashRegex(R"(,\s*hash)");
|
197
|
+
removeGroup(base, hashRegex);
|
128
198
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
199
|
+
// Remove equal_to (std::unordered_map)
|
200
|
+
std::regex equalRegex(R"(,\s*equal_to)");
|
201
|
+
removeGroup(base, equalRegex);
|
202
|
+
|
203
|
+
// Remove spaces before pointers
|
204
|
+
auto ptrRegex = std::regex(R"(\s+\*)");
|
205
|
+
base = std::regex_replace(base, ptrRegex, "*");
|
206
|
+
|
207
|
+
// Remove __ptr64
|
208
|
+
std::regex ptr64Regex(R"(\s*__ptr64\s*)");
|
209
|
+
base = std::regex_replace(base, ptr64Regex, "");
|
210
|
+
|
211
|
+
// Replace " >" with ">"
|
212
|
+
auto trailingAngleBracketSpaceRegex = std::regex(R"(\s+>)");
|
213
|
+
replaceAll(base, trailingAngleBracketSpaceRegex, ">");
|
214
|
+
|
215
|
+
// One space after a comma (MSVC has no spaces, GCC one space)
|
216
|
+
auto commaSpaceRegex = std::regex(R"(,(\S))");
|
217
|
+
replaceAll(base, commaSpaceRegex, ", $1");
|
218
|
+
|
219
|
+
// Capitalize first letter
|
220
|
+
base[0] = std::toupper(base[0]);
|
221
|
+
|
222
|
+
// Replace :: with unicode U+u02F8 (Modified Letter raised colon)
|
223
|
+
auto colonRegex = std::regex(R"(:)");
|
224
|
+
replaceAll(base, colonRegex, "\uA789");
|
225
|
+
|
226
|
+
// Replace _ and capitalize the next letter
|
227
|
+
std::regex namespaceRegex(R"(_(\w))");
|
228
|
+
std::smatch namespaceMatch;
|
229
|
+
while (std::regex_search(base, namespaceMatch, namespaceRegex))
|
230
|
+
{
|
231
|
+
std::string replacement = namespaceMatch[1];
|
232
|
+
std::transform(replacement.begin(), replacement.end(), replacement.begin(), ::toupper);
|
233
|
+
base.replace(namespaceMatch.position(), namespaceMatch.length(), replacement);
|
234
|
+
}
|
235
|
+
|
236
|
+
// Replace spaces with unicode U+u00A0 (Non breaking Space)
|
237
|
+
auto spaceRegex = std::regex(R"(\s+)");
|
238
|
+
replaceAll(base, spaceRegex, "\u00A0");
|
239
|
+
|
240
|
+
// Replace < with unicode U+227A (Precedes)
|
241
|
+
auto lessThanRegex = std::regex("<");
|
242
|
+
//replaceAll(base, lessThanRegex, u8"≺");
|
243
|
+
replaceAll(base, lessThanRegex, "\u227A");
|
244
|
+
|
245
|
+
// Replace > with unicode U+227B (Succeeds)
|
246
|
+
auto greaterThanRegex = std::regex(">");
|
247
|
+
//replaceAll(base, greaterThanRegex, u8"≻");
|
248
|
+
replaceAll(base, greaterThanRegex, "\u227B");
|
249
|
+
|
250
|
+
// Replace , with Unicode Character (U+066C) - Arabic Thousands Separator
|
251
|
+
auto commaRegex = std::regex(R"(,\s*)");
|
252
|
+
replaceAll(base, commaRegex, "\u201A");
|
136
253
|
|
137
|
-
return
|
254
|
+
return base;
|
138
255
|
}
|
139
256
|
}
|
@@ -2,12 +2,10 @@
|
|
2
2
|
#define Rice__TypeRegistry__hpp_
|
3
3
|
|
4
4
|
#include <optional>
|
5
|
-
#include <string>
|
6
|
-
#include <typeindex>
|
7
|
-
#include <typeinfo>
|
8
5
|
#include <unordered_map>
|
6
|
+
#include <set>
|
7
|
+
#include <regex>
|
9
8
|
|
10
|
-
#include "ruby.hpp"
|
11
9
|
|
12
10
|
/* The type registry keeps track of all C++ types wrapped by Rice. When a native function returns
|
13
11
|
an instance of a class/struct we look up its type to verity that it has been registered.
|
@@ -31,17 +29,27 @@ namespace Rice::detail
|
|
31
29
|
bool isDefined();
|
32
30
|
|
33
31
|
template <typename T>
|
34
|
-
|
32
|
+
std::pair<VALUE, rb_data_type_t*> getType();
|
33
|
+
|
34
|
+
template <typename T>
|
35
|
+
bool verify();
|
35
36
|
|
36
37
|
template <typename T>
|
37
38
|
std::pair<VALUE, rb_data_type_t*> figureType(const T& object);
|
38
39
|
|
40
|
+
// Validate types and throw if any types are unverified
|
41
|
+
void validateTypes();
|
42
|
+
|
43
|
+
// Clear unverified types. This is mostly for unit tests
|
44
|
+
void clearUnverifiedTypes();
|
45
|
+
|
39
46
|
private:
|
40
47
|
std::optional<std::pair<VALUE, rb_data_type_t*>> lookup(const std::type_info& typeInfo);
|
48
|
+
void raiseUnverifiedType(const std::string& typeName);
|
49
|
+
|
41
50
|
std::unordered_map<std::type_index, std::pair<VALUE, rb_data_type_t*>> registry_{};
|
51
|
+
std::set<std::type_index> unverified_{};
|
42
52
|
};
|
43
53
|
}
|
44
54
|
|
45
|
-
#include "TypeRegistry.ipp"
|
46
|
-
|
47
55
|
#endif // Rice__TypeRegistry__hpp_
|
@@ -1,8 +1,8 @@
|
|
1
|
+
#include <iostream>
|
1
2
|
#include <stdexcept>
|
3
|
+
#include <sstream>
|
4
|
+
#include <typeindex>
|
2
5
|
|
3
|
-
#include "ruby.hpp"
|
4
|
-
#include "../traits/rice_traits.hpp"
|
5
|
-
#include "Type.hpp"
|
6
6
|
|
7
7
|
namespace Rice::detail
|
8
8
|
{
|
@@ -13,6 +13,22 @@ namespace Rice::detail
|
|
13
13
|
registry_[key] = std::pair(klass, rbType);
|
14
14
|
}
|
15
15
|
|
16
|
+
/* Special case void. Rice defines classes using the class name not a pointer to the
|
17
|
+
class. Thus define_class<void> is more consistent with Rice then
|
18
|
+
define_class<void*>. However, the types of void and void* are different so we need
|
19
|
+
this special case.
|
20
|
+
|
21
|
+
It is possible to support define_class<void*>, but it requires changing the static
|
22
|
+
assertions on Data_Type and Data_Object and thus seems less desirable (and less
|
23
|
+
consistent as mentioned above).*/
|
24
|
+
template <>
|
25
|
+
inline void TypeRegistry::add<void>(VALUE klass, rb_data_type_t* rbType)
|
26
|
+
{
|
27
|
+
// The special case, use void*
|
28
|
+
std::type_index key(typeid(void*));
|
29
|
+
registry_[key] = std::pair(klass, rbType);
|
30
|
+
}
|
31
|
+
|
16
32
|
template <typename T>
|
17
33
|
inline void TypeRegistry::remove()
|
18
34
|
{
|
@@ -29,14 +45,45 @@ namespace Rice::detail
|
|
29
45
|
}
|
30
46
|
|
31
47
|
template <typename T>
|
32
|
-
|
48
|
+
std::pair<VALUE, rb_data_type_t*> TypeRegistry::getType()
|
33
49
|
{
|
34
|
-
|
50
|
+
std::type_index key(typeid(T));
|
51
|
+
auto iter = registry_.find(key);
|
52
|
+
if (iter != registry_.end())
|
35
53
|
{
|
36
|
-
|
37
|
-
|
54
|
+
return iter->second;
|
55
|
+
}
|
56
|
+
else
|
57
|
+
{
|
58
|
+
this->raiseUnverifiedType(typeid(T).name());
|
59
|
+
// Make compiler happy
|
60
|
+
return std::make_pair(Qnil, nullptr);
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
// Special case void. See comment for add above.
|
65
|
+
template <>
|
66
|
+
inline bool TypeRegistry::isDefined<void>()
|
67
|
+
{
|
68
|
+
std::type_index key(typeid(void*));
|
69
|
+
auto iter = registry_.find(key);
|
70
|
+
return iter != registry_.end();
|
71
|
+
}
|
72
|
+
|
73
|
+
template <typename T>
|
74
|
+
inline bool TypeRegistry::verify()
|
75
|
+
{
|
76
|
+
if (isDefined<T>())
|
77
|
+
{
|
78
|
+
return true;
|
79
|
+
}
|
80
|
+
else
|
81
|
+
{
|
82
|
+
const std::type_info& typeInfo = typeid(T);
|
83
|
+
std::type_index key(typeInfo);
|
84
|
+
this->unverified_.insert(key);
|
85
|
+
return false;
|
38
86
|
}
|
39
|
-
return true;
|
40
87
|
}
|
41
88
|
|
42
89
|
inline std::optional<std::pair<VALUE, rb_data_type_t*>> TypeRegistry::lookup(const std::type_info& typeInfo)
|
@@ -68,14 +115,60 @@ namespace Rice::detail
|
|
68
115
|
// If not, then we are willing to accept an ancestor class specified by T. This is needed
|
69
116
|
// to support Directors. Classes inherited from Directors are never actually registered
|
70
117
|
// with Rice - and what we really want it to return the C++ class they inherit from.
|
71
|
-
|
118
|
+
const std::type_info& typeInfo = typeid(T);
|
119
|
+
result = lookup(typeInfo);
|
72
120
|
if (result)
|
73
121
|
{
|
74
122
|
return result.value();
|
75
123
|
}
|
76
124
|
|
77
|
-
|
78
|
-
|
79
|
-
|
125
|
+
raiseUnverifiedType(detail::typeName(typeInfo));
|
126
|
+
// Make the compiler happy
|
127
|
+
return std::pair<VALUE, rb_data_type_t*>(Qnil, nullptr);
|
128
|
+
}
|
129
|
+
|
130
|
+
inline void TypeRegistry::validateTypes()
|
131
|
+
{
|
132
|
+
// Loop over the unverified types and delete each on that is found in the registry
|
133
|
+
// the registry and raise an exception for the first one that is not
|
134
|
+
for (auto iter = this->unverified_.begin(); iter != this->unverified_.end(); )
|
135
|
+
{
|
136
|
+
const std::type_index& typeIndex = *iter;
|
137
|
+
bool isDefined = this->registry_.find(typeIndex) != this->registry_.end();
|
138
|
+
if (isDefined)
|
139
|
+
{
|
140
|
+
iter = this->unverified_.erase(iter);
|
141
|
+
}
|
142
|
+
else
|
143
|
+
{
|
144
|
+
iter++;
|
145
|
+
}
|
146
|
+
}
|
147
|
+
|
148
|
+
if (this->unverified_.empty())
|
149
|
+
{
|
150
|
+
return;
|
151
|
+
}
|
152
|
+
|
153
|
+
std::stringstream stream;
|
154
|
+
stream << "The following types are not registered with Rice:" << "\n";
|
155
|
+
|
156
|
+
for (const std::type_index& typeIndex : this->unverified_)
|
157
|
+
{
|
158
|
+
stream << " " << typeName(typeIndex) << "\n";
|
159
|
+
}
|
160
|
+
|
161
|
+
throw std::invalid_argument(stream.str());
|
162
|
+
}
|
163
|
+
|
164
|
+
inline void TypeRegistry::clearUnverifiedTypes()
|
165
|
+
{
|
166
|
+
this->unverified_.clear();
|
167
|
+
}
|
168
|
+
|
169
|
+
inline void TypeRegistry::raiseUnverifiedType(const std::string& typeName)
|
170
|
+
{
|
171
|
+
std::string message = "Type is not registered with Rice: " + typeName;
|
172
|
+
throw std::invalid_argument(message);
|
80
173
|
}
|
81
174
|
}
|
data/rice/detail/Wrapper.hpp
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
#ifndef Rice__detail__Wrapper__hpp_
|
2
2
|
#define Rice__detail__Wrapper__hpp_
|
3
3
|
|
4
|
-
#include "ruby.hpp"
|
5
|
-
|
6
4
|
namespace Rice
|
7
5
|
{
|
8
6
|
namespace detail
|
@@ -11,11 +9,16 @@ namespace detail
|
|
11
9
|
class Wrapper
|
12
10
|
{
|
13
11
|
public:
|
12
|
+
Wrapper(bool isOwner = false);
|
14
13
|
virtual ~Wrapper() = default;
|
15
14
|
virtual void* get() = 0;
|
16
15
|
|
17
16
|
void ruby_mark();
|
18
17
|
void addKeepAlive(VALUE value);
|
18
|
+
void setOwner(bool value);
|
19
|
+
|
20
|
+
protected:
|
21
|
+
bool isOwner_ = false;
|
19
22
|
|
20
23
|
private:
|
21
24
|
// We use a vector for speed and memory locality versus a set which does
|
@@ -31,7 +34,7 @@ template <typename T, typename Wrapper_T = void>
|
|
31
34
|
VALUE wrap(VALUE klass, rb_data_type_t* rb_type, T* data, bool isOwner);
|
32
35
|
|
33
36
|
template <typename T>
|
34
|
-
T* unwrap(VALUE value, rb_data_type_t* rb_type);
|
37
|
+
T* unwrap(VALUE value, rb_data_type_t* rb_type, bool takeOwnership);
|
35
38
|
|
36
39
|
Wrapper* getWrapper(VALUE value, rb_data_type_t* rb_type);
|
37
40
|
|
@@ -43,7 +46,5 @@ Wrapper* getWrapper(VALUE value);
|
|
43
46
|
} // namespace detail
|
44
47
|
} // namespace Rice
|
45
48
|
|
46
|
-
#include "Wrapper.ipp"
|
47
|
-
|
48
49
|
#endif // Rice__detail__Wrapper__hpp_
|
49
50
|
|
data/rice/detail/Wrapper.ipp
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
#include <memory>
|
2
|
-
#include "InstanceRegistry.hpp"
|
3
2
|
|
4
3
|
namespace Rice::detail
|
5
4
|
{
|
5
|
+
inline Wrapper::Wrapper(bool isOwner): isOwner_(isOwner)
|
6
|
+
{
|
7
|
+
}
|
8
|
+
|
6
9
|
inline void Wrapper::ruby_mark()
|
7
10
|
{
|
8
11
|
for (VALUE value : this->keepAlive_)
|
@@ -16,6 +19,11 @@ namespace Rice::detail
|
|
16
19
|
this->keepAlive_.push_back(value);
|
17
20
|
}
|
18
21
|
|
22
|
+
inline void Wrapper::setOwner(bool value)
|
23
|
+
{
|
24
|
+
this->isOwner_ = value;
|
25
|
+
}
|
26
|
+
|
19
27
|
template <typename T>
|
20
28
|
class WrapperValue : public Wrapper
|
21
29
|
{
|
@@ -64,7 +72,7 @@ namespace Rice::detail
|
|
64
72
|
class WrapperPointer : public Wrapper
|
65
73
|
{
|
66
74
|
public:
|
67
|
-
WrapperPointer(T* data, bool isOwner) :
|
75
|
+
WrapperPointer(T* data, bool isOwner) : Wrapper(isOwner), data_(data)
|
68
76
|
{
|
69
77
|
}
|
70
78
|
|
@@ -72,9 +80,12 @@ namespace Rice::detail
|
|
72
80
|
{
|
73
81
|
Registries::instance.instances.remove(this->get());
|
74
82
|
|
75
|
-
if (
|
83
|
+
if constexpr (std::is_destructible_v<T>)
|
76
84
|
{
|
77
|
-
|
85
|
+
if (this->isOwner_)
|
86
|
+
{
|
87
|
+
delete this->data_;
|
88
|
+
}
|
78
89
|
}
|
79
90
|
}
|
80
91
|
|
@@ -85,7 +96,6 @@ namespace Rice::detail
|
|
85
96
|
|
86
97
|
private:
|
87
98
|
T* data_ = nullptr;
|
88
|
-
bool isOwner_ = false;
|
89
99
|
};
|
90
100
|
|
91
101
|
// ---- Helper Functions -------
|
@@ -111,12 +121,20 @@ namespace Rice::detail
|
|
111
121
|
wrapper = new Wrapper_T(data);
|
112
122
|
result = TypedData_Wrap_Struct(klass, rb_type, wrapper);
|
113
123
|
}
|
114
|
-
//
|
115
|
-
// If ruby is the owner than copy the object
|
124
|
+
// If ruby is the owner than copy the object if possible
|
116
125
|
else if (isOwner)
|
117
126
|
{
|
118
|
-
|
119
|
-
|
127
|
+
if constexpr (std::is_copy_constructible_v<T> || std::is_move_constructible_v<T>)
|
128
|
+
{
|
129
|
+
wrapper = new WrapperValue<T>(data);
|
130
|
+
result = TypedData_Wrap_Struct(klass, rb_type, wrapper);
|
131
|
+
}
|
132
|
+
else
|
133
|
+
{
|
134
|
+
std::string message = "Ruby was directed to take ownership of a C++ object but it does not have an accessible copy or move constructor. Type: " +
|
135
|
+
typeName(typeid(T));
|
136
|
+
throw std::runtime_error(message);
|
137
|
+
}
|
120
138
|
}
|
121
139
|
// Ruby is not the owner so just wrap the reference
|
122
140
|
else
|
@@ -156,9 +174,11 @@ namespace Rice::detail
|
|
156
174
|
};
|
157
175
|
|
158
176
|
template <typename T>
|
159
|
-
inline T* unwrap(VALUE value, rb_data_type_t* rb_type)
|
177
|
+
inline T* unwrap(VALUE value, rb_data_type_t* rb_type, bool takeOwnership)
|
160
178
|
{
|
161
179
|
Wrapper* wrapper = getWrapper(value, rb_type);
|
180
|
+
if (takeOwnership)
|
181
|
+
wrapper->setOwner(false);
|
162
182
|
|
163
183
|
if (wrapper == nullptr)
|
164
184
|
{
|
@@ -179,6 +199,21 @@ namespace Rice::detail
|
|
179
199
|
return wrapper;
|
180
200
|
}
|
181
201
|
|
202
|
+
inline Wrapper* getWrapper(VALUE value)
|
203
|
+
{
|
204
|
+
// Turn off spurious warning on g++ 12
|
205
|
+
#if defined(__GNUC__) || defined(__clang__)
|
206
|
+
#pragma GCC diagnostic push
|
207
|
+
#pragma GCC diagnostic ignored "-Warray-bounds"
|
208
|
+
#endif
|
209
|
+
|
210
|
+
return RTYPEDDATA_P(value) ? static_cast<Wrapper*>(RTYPEDDATA_DATA(value)) : nullptr;
|
211
|
+
|
212
|
+
#if defined(__GNUC__) || defined(__clang__)
|
213
|
+
#pragma GCC diagnostic pop
|
214
|
+
#endif
|
215
|
+
}
|
216
|
+
|
182
217
|
template <typename T>
|
183
218
|
inline void replace(VALUE value, rb_data_type_t* rb_type, T* data, bool isOwner)
|
184
219
|
{
|
@@ -195,17 +230,4 @@ namespace Rice::detail
|
|
195
230
|
|
196
231
|
Registries::instance.instances.add(data, value);
|
197
232
|
}
|
198
|
-
|
199
|
-
inline Wrapper* getWrapper(VALUE value)
|
200
|
-
{
|
201
|
-
// Turn off spurious warning on g++ 12
|
202
|
-
#ifdef __GNUC__
|
203
|
-
#pragma GCC diagnostic push
|
204
|
-
#pragma GCC diagnostic ignored "-Warray-bounds"
|
205
|
-
#endif
|
206
|
-
return RTYPEDDATA_P(value) ? static_cast<Wrapper*>(RTYPEDDATA_DATA(value)) : nullptr;
|
207
|
-
#ifdef __GNUC__
|
208
|
-
#pragma GCC diagnostic pop
|
209
|
-
#endif
|
210
|
-
}
|
211
233
|
} // namespace
|
data/rice/detail/cpp_protect.hpp
CHANGED
@@ -14,8 +14,6 @@
|
|
14
14
|
#error "no filesystem include found :'("
|
15
15
|
#endif
|
16
16
|
|
17
|
-
#include "Jump_Tag.hpp"
|
18
|
-
#include "../Exception_defn.hpp"
|
19
17
|
|
20
18
|
namespace Rice::detail
|
21
19
|
{
|
@@ -30,13 +28,14 @@ namespace Rice::detail
|
|
30
28
|
{
|
31
29
|
try
|
32
30
|
{
|
33
|
-
detail::Registries::instance.handlers.handler()
|
31
|
+
std::function<void()> handler = detail::Registries::instance.handlers.handler();
|
32
|
+
handler();
|
34
33
|
}
|
35
34
|
catch (::Rice::Exception const& ex)
|
36
35
|
{
|
37
36
|
rb_exc_raise(ex.value());
|
38
37
|
}
|
39
|
-
catch (::Rice::
|
38
|
+
catch (::Rice::JumpException const& ex)
|
40
39
|
{
|
41
40
|
rb_jump_tag(ex.tag);
|
42
41
|
}
|
@@ -61,11 +60,11 @@ namespace Rice::detail
|
|
61
60
|
}
|
62
61
|
catch (std::length_error const& ex)
|
63
62
|
{
|
64
|
-
rb_exc_raise(rb_exc_new2(
|
63
|
+
rb_exc_raise(rb_exc_new2(rb_eIndexError, ex.what()));
|
65
64
|
}
|
66
65
|
catch (std::out_of_range const& ex)
|
67
66
|
{
|
68
|
-
rb_exc_raise(rb_exc_new2(
|
67
|
+
rb_exc_raise(rb_exc_new2(rb_eIndexError, ex.what()));
|
69
68
|
}
|
70
69
|
catch (std::overflow_error const& ex)
|
71
70
|
{
|
data/rice/detail/from_ruby.hpp
CHANGED
@@ -1,8 +1,42 @@
|
|
1
1
|
#ifndef Rice__detail__from_ruby__hpp_
|
2
2
|
#define Rice__detail__from_ruby__hpp_
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
namespace Rice::detail
|
5
|
+
{
|
6
|
+
//! Convert a Ruby object to C++.
|
7
|
+
/*! If the Ruby object can be converted to an immediate value, returns a
|
8
|
+
* copy of the Ruby object. If the Ruby object is holding a C++
|
9
|
+
* object and the type specified is a pointer to that type, returns a
|
10
|
+
* pointer to that object.
|
11
|
+
*
|
12
|
+
* Conversions from ruby to a pointer type are automatically generated
|
13
|
+
* when a type is bound using Data_Type. If no conversion exists an
|
14
|
+
* exception is thrown.
|
15
|
+
*
|
16
|
+
* \param T the C++ type to which to convert.
|
17
|
+
* \param x the Ruby object to convert.
|
18
|
+
* \return a C++ representation of the Ruby object.
|
19
|
+
*
|
20
|
+
* Example:
|
21
|
+
* \code
|
22
|
+
* Object x = INT2NUM(42);
|
23
|
+
* std::cout << From_Ruby<int>::convert(x);
|
24
|
+
*
|
25
|
+
* Data_Object<Foo> foo(new Foo);
|
26
|
+
* std::cout << *From_Ruby<Foo *>(foo) << std::endl;
|
27
|
+
* \endcode
|
28
|
+
*/
|
6
29
|
|
7
|
-
|
30
|
+
template <typename T>
|
31
|
+
class From_Ruby;
|
8
32
|
|
33
|
+
enum class Convertible: uint8_t
|
34
|
+
{
|
35
|
+
None = 0b000,
|
36
|
+
Narrowable = 0b001,
|
37
|
+
Cast = 0b011,
|
38
|
+
Exact = 0b111,
|
39
|
+
};
|
40
|
+
}
|
41
|
+
|
42
|
+
#endif // Rice__detail__From_Ruby2__hpp_
|