rice 4.3.3 → 4.6.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.
Files changed (237) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +86 -26
  3. data/CMakeLists.txt +31 -0
  4. data/CMakePresets.json +75 -0
  5. data/COPYING +3 -2
  6. data/FindRuby.cmake +437 -0
  7. data/README.md +7 -2
  8. data/Rakefile +12 -5
  9. data/include/rice/rice.hpp +9522 -4426
  10. data/include/rice/stl.hpp +2831 -1198
  11. data/lib/make_rice_headers.rb +79 -0
  12. data/lib/mkmf-rice.rb +40 -94
  13. data/lib/rice/version.rb +3 -0
  14. data/lib/rice.rb +1 -0
  15. data/lib/rubygems/builder.rb +11 -0
  16. data/lib/rubygems/cmake_builder.rb +113 -0
  17. data/lib/rubygems_plugin.rb +9 -0
  18. data/rice/Address_Registration_Guard.hpp +72 -3
  19. data/rice/Arg.hpp +26 -6
  20. data/rice/Arg.ipp +35 -2
  21. data/rice/Buffer.hpp +123 -0
  22. data/rice/Buffer.ipp +599 -0
  23. data/rice/Callback.hpp +21 -0
  24. data/rice/Callback.ipp +13 -0
  25. data/rice/Constructor.hpp +4 -27
  26. data/rice/Constructor.ipp +79 -0
  27. data/rice/Data_Object.hpp +73 -3
  28. data/rice/Data_Object.ipp +388 -96
  29. data/rice/Data_Type.hpp +214 -3
  30. data/rice/Data_Type.ipp +144 -67
  31. data/rice/Director.hpp +0 -2
  32. data/rice/Enum.hpp +4 -7
  33. data/rice/Enum.ipp +102 -55
  34. data/rice/Exception.hpp +62 -2
  35. data/rice/Exception.ipp +7 -12
  36. data/rice/Init.hpp +8 -0
  37. data/rice/Init.ipp +8 -0
  38. data/rice/JumpException.hpp +44 -0
  39. data/rice/JumpException.ipp +48 -0
  40. data/rice/MemoryView.hpp +11 -0
  41. data/rice/MemoryView.ipp +3 -0
  42. data/rice/Return.hpp +7 -27
  43. data/rice/Return.ipp +13 -13
  44. data/rice/cpp_api/Array.hpp +209 -0
  45. data/rice/cpp_api/Array.ipp +304 -0
  46. data/rice/cpp_api/Builtin_Object.hpp +31 -0
  47. data/rice/cpp_api/Builtin_Object.ipp +37 -0
  48. data/rice/cpp_api/Class.hpp +70 -0
  49. data/rice/cpp_api/Class.ipp +97 -0
  50. data/rice/cpp_api/Encoding.hpp +32 -0
  51. data/rice/cpp_api/Encoding.ipp +59 -0
  52. data/rice/cpp_api/Hash.hpp +194 -0
  53. data/rice/cpp_api/Hash.ipp +257 -0
  54. data/rice/{Identifier.hpp → cpp_api/Identifier.hpp} +2 -6
  55. data/rice/{Identifier.ipp → cpp_api/Identifier.ipp} +4 -2
  56. data/rice/cpp_api/Module.hpp +72 -0
  57. data/rice/cpp_api/Module.ipp +101 -0
  58. data/rice/cpp_api/Object.hpp +272 -0
  59. data/rice/cpp_api/Object.ipp +235 -0
  60. data/rice/cpp_api/String.hpp +74 -0
  61. data/rice/cpp_api/String.ipp +120 -0
  62. data/rice/cpp_api/Struct.hpp +113 -0
  63. data/rice/cpp_api/Struct.ipp +92 -0
  64. data/rice/cpp_api/Symbol.hpp +46 -0
  65. data/rice/cpp_api/Symbol.ipp +93 -0
  66. data/rice/cpp_api/shared_methods.hpp +134 -0
  67. data/rice/detail/DefaultHandler.hpp +12 -0
  68. data/rice/detail/DefaultHandler.ipp +8 -0
  69. data/rice/detail/HandlerRegistry.hpp +5 -35
  70. data/rice/detail/HandlerRegistry.ipp +7 -11
  71. data/rice/detail/InstanceRegistry.hpp +1 -4
  72. data/rice/detail/MethodInfo.hpp +12 -10
  73. data/rice/detail/MethodInfo.ipp +26 -21
  74. data/rice/detail/Native.hpp +33 -0
  75. data/rice/detail/Native.ipp +157 -0
  76. data/rice/detail/NativeAttributeGet.hpp +52 -0
  77. data/rice/detail/NativeAttributeGet.ipp +57 -0
  78. data/rice/detail/NativeAttributeSet.hpp +44 -0
  79. data/rice/detail/NativeAttributeSet.ipp +88 -0
  80. data/rice/detail/NativeCallbackFFI.hpp +55 -0
  81. data/rice/detail/NativeCallbackFFI.ipp +151 -0
  82. data/rice/detail/NativeCallbackSimple.hpp +30 -0
  83. data/rice/detail/NativeCallbackSimple.ipp +29 -0
  84. data/rice/detail/NativeFunction.hpp +33 -23
  85. data/rice/detail/NativeFunction.ipp +309 -70
  86. data/rice/detail/NativeIterator.hpp +9 -11
  87. data/rice/detail/NativeIterator.ipp +33 -31
  88. data/rice/detail/NativeRegistry.hpp +24 -15
  89. data/rice/detail/NativeRegistry.ipp +23 -48
  90. data/rice/detail/Proc.hpp +4 -0
  91. data/rice/detail/Proc.ipp +85 -0
  92. data/rice/detail/Registries.hpp +0 -7
  93. data/rice/detail/Registries.ipp +0 -18
  94. data/rice/detail/RubyFunction.hpp +0 -3
  95. data/rice/detail/RubyFunction.ipp +4 -8
  96. data/rice/detail/RubyType.hpp +16 -0
  97. data/rice/detail/RubyType.ipp +232 -0
  98. data/rice/detail/Type.hpp +7 -6
  99. data/rice/detail/Type.ipp +192 -45
  100. data/rice/detail/TypeRegistry.hpp +15 -7
  101. data/rice/detail/TypeRegistry.ipp +105 -12
  102. data/rice/detail/Wrapper.hpp +68 -32
  103. data/rice/detail/Wrapper.ipp +121 -109
  104. data/rice/detail/cpp_protect.hpp +5 -6
  105. data/rice/detail/default_allocation_func.ipp +0 -2
  106. data/rice/detail/from_ruby.hpp +38 -3
  107. data/rice/detail/from_ruby.ipp +1321 -492
  108. data/rice/detail/ruby.hpp +18 -0
  109. data/rice/detail/to_ruby.hpp +41 -3
  110. data/rice/detail/to_ruby.ipp +1424 -194
  111. data/rice/global_function.hpp +0 -4
  112. data/rice/global_function.ipp +0 -1
  113. data/rice/libc/file.hpp +11 -0
  114. data/rice/libc/file.ipp +32 -0
  115. data/rice/rice.hpp +116 -26
  116. data/rice/ruby_mark.hpp +4 -3
  117. data/rice/stl/complex.hpp +6 -0
  118. data/rice/stl/complex.ipp +93 -0
  119. data/rice/stl/exception.hpp +11 -0
  120. data/rice/stl/exception.ipp +29 -0
  121. data/rice/stl/exception_ptr.hpp +6 -0
  122. data/rice/stl/exception_ptr.ipp +27 -0
  123. data/rice/stl/map.hpp +12 -0
  124. data/rice/stl/map.ipp +469 -0
  125. data/rice/stl/monostate.hpp +6 -0
  126. data/rice/stl/monostate.ipp +80 -0
  127. data/rice/stl/multimap.hpp +14 -0
  128. data/rice/stl/multimap.ipp +448 -0
  129. data/rice/stl/optional.hpp +6 -0
  130. data/rice/stl/optional.ipp +118 -0
  131. data/rice/stl/pair.hpp +13 -0
  132. data/rice/stl/pair.ipp +155 -0
  133. data/rice/stl/reference_wrapper.hpp +6 -0
  134. data/rice/stl/reference_wrapper.ipp +41 -0
  135. data/rice/stl/set.hpp +12 -0
  136. data/rice/stl/set.ipp +495 -0
  137. data/rice/stl/shared_ptr.hpp +28 -0
  138. data/rice/stl/shared_ptr.ipp +224 -0
  139. data/rice/stl/string.hpp +6 -0
  140. data/rice/stl/string.ipp +158 -0
  141. data/rice/stl/string_view.hpp +6 -0
  142. data/rice/stl/string_view.ipp +65 -0
  143. data/rice/stl/tuple.hpp +6 -0
  144. data/rice/stl/tuple.ipp +128 -0
  145. data/rice/stl/type_index.hpp +6 -0
  146. data/rice/stl/type_index.ipp +30 -0
  147. data/rice/stl/type_info.hpp +6 -0
  148. data/rice/stl/type_info.ipp +29 -0
  149. data/rice/stl/unique_ptr.hpp +22 -0
  150. data/rice/stl/unique_ptr.ipp +139 -0
  151. data/rice/stl/unordered_map.hpp +12 -0
  152. data/rice/stl/unordered_map.ipp +469 -0
  153. data/rice/stl/variant.hpp +6 -0
  154. data/rice/stl/variant.ipp +242 -0
  155. data/rice/stl/vector.hpp +12 -0
  156. data/rice/stl/vector.ipp +590 -0
  157. data/rice/stl.hpp +11 -3
  158. data/rice/traits/attribute_traits.hpp +26 -0
  159. data/rice/traits/function_traits.hpp +95 -0
  160. data/rice/traits/method_traits.hpp +47 -0
  161. data/rice/traits/rice_traits.hpp +160 -0
  162. data/rice.gemspec +85 -0
  163. data/test/embed_ruby.cpp +7 -1
  164. data/test/extconf.rb +2 -0
  165. data/test/test_Address_Registration_Guard.cpp +5 -0
  166. data/test/test_Array.cpp +18 -4
  167. data/test/test_Attribute.cpp +136 -21
  168. data/test/test_Buffer.cpp +285 -0
  169. data/test/test_Builtin_Object.cpp +5 -0
  170. data/test/test_Callback.cpp +230 -0
  171. data/test/test_Class.cpp +5 -31
  172. data/test/test_Constructor.cpp +69 -6
  173. data/test/test_Data_Object.cpp +97 -38
  174. data/test/test_Data_Type.cpp +470 -65
  175. data/test/test_Director.cpp +17 -8
  176. data/test/test_Enum.cpp +155 -40
  177. data/test/test_Exception.cpp +235 -0
  178. data/test/test_File.cpp +70 -0
  179. data/test/test_From_Ruby.cpp +609 -0
  180. data/test/test_Hash.cpp +5 -0
  181. data/test/test_Identifier.cpp +5 -0
  182. data/test/test_Inheritance.cpp +6 -1
  183. data/test/test_Iterator.cpp +6 -1
  184. data/test/test_Jump_Exception.cpp +23 -0
  185. data/test/test_Keep_Alive.cpp +13 -19
  186. data/test/test_Keep_Alive_No_Wrapper.cpp +5 -1
  187. data/test/test_Memory_Management.cpp +5 -0
  188. data/test/test_Module.cpp +128 -67
  189. data/test/test_Native_Registry.cpp +2 -34
  190. data/test/test_Object.cpp +5 -0
  191. data/test/test_Overloads.cpp +806 -0
  192. data/test/test_Ownership.cpp +160 -54
  193. data/test/test_Proc.cpp +44 -0
  194. data/test/test_Self.cpp +9 -4
  195. data/test/test_Stl_Exception.cpp +109 -0
  196. data/test/test_Stl_Map.cpp +54 -42
  197. data/test/test_Stl_Multimap.cpp +693 -0
  198. data/test/test_Stl_Optional.cpp +5 -0
  199. data/test/test_Stl_Pair.cpp +14 -9
  200. data/test/test_Stl_Reference_Wrapper.cpp +9 -2
  201. data/test/test_Stl_Set.cpp +790 -0
  202. data/test/test_Stl_SharedPtr.cpp +458 -0
  203. data/test/test_Stl_String.cpp +5 -0
  204. data/test/test_Stl_String_View.cpp +5 -0
  205. data/test/test_Stl_Tuple.cpp +116 -0
  206. data/test/test_Stl_Type.cpp +147 -0
  207. data/test/test_Stl_UniquePtr.cpp +202 -0
  208. data/test/test_Stl_Unordered_Map.cpp +43 -38
  209. data/test/test_Stl_Variant.cpp +217 -84
  210. data/test/test_Stl_Vector.cpp +306 -58
  211. data/test/test_String.cpp +5 -0
  212. data/test/test_Struct.cpp +5 -0
  213. data/test/test_Symbol.cpp +5 -0
  214. data/test/test_Template.cpp +192 -0
  215. data/test/test_To_Ruby.cpp +524 -0
  216. data/test/test_Tracking.cpp +1 -0
  217. data/test/test_Type.cpp +171 -0
  218. data/test/test_global_functions.cpp +67 -7
  219. data/test/unittest.cpp +8 -0
  220. metadata +127 -26
  221. data/lib/version.rb +0 -3
  222. data/rice/Address_Registration_Guard_defn.hpp +0 -79
  223. data/rice/Data_Object_defn.hpp +0 -84
  224. data/rice/Data_Type_defn.hpp +0 -190
  225. data/rice/Exception_defn.hpp +0 -68
  226. data/rice/HandlerRegistration.hpp +0 -15
  227. data/rice/detail/ExceptionHandler.hpp +0 -8
  228. data/rice/detail/ExceptionHandler.ipp +0 -28
  229. data/rice/detail/ExceptionHandler_defn.hpp +0 -77
  230. data/rice/detail/Jump_Tag.hpp +0 -21
  231. data/rice/detail/NativeAttribute.hpp +0 -64
  232. data/rice/detail/NativeAttribute.ipp +0 -112
  233. data/rice/detail/from_ruby_defn.hpp +0 -38
  234. data/rice/detail/to_ruby_defn.hpp +0 -48
  235. data/test/test_Jump_Tag.cpp +0 -17
  236. data/test/test_Stl_SmartPointer.cpp +0 -283
  237. data/test/test_To_From_Ruby.cpp +0 -399
data/rice/Data_Object.ipp CHANGED
@@ -1,7 +1,3 @@
1
- #ifndef Rice__Data_Object__ipp_
2
- #define Rice__Data_Object__ipp_
3
-
4
- #include "Data_Type_defn.hpp"
5
1
 
6
2
  #include <algorithm>
7
3
 
@@ -22,6 +18,20 @@ namespace Rice
22
18
  this->set_value(value);
23
19
  }
24
20
 
21
+ template<typename T>
22
+ inline Data_Object<T>::Data_Object(T&& data, Class klass)
23
+ {
24
+ VALUE value = detail::wrap(klass, Data_Type<T>::ruby_data_type(), data, true);
25
+ this->set_value(value);
26
+ }
27
+
28
+ template<typename T>
29
+ inline Data_Object<T>::Data_Object(const T& data, bool isOwner, Class klass)
30
+ {
31
+ VALUE value = detail::wrap(klass, Data_Type<T>::ruby_data_type(), data, isOwner);
32
+ this->set_value(value);
33
+ }
34
+
25
35
  template<typename T>
26
36
  inline Data_Object<T>::Data_Object(T* data, bool isOwner, Class klass)
27
37
  {
@@ -35,6 +45,12 @@ namespace Rice
35
45
  check_ruby_type(value);
36
46
  }
37
47
 
48
+ template<typename T>
49
+ inline Data_Object<T>::Data_Object(VALUE value) : Object(value)
50
+ {
51
+ check_ruby_type(value);
52
+ }
53
+
38
54
  template<typename T>
39
55
  inline void Data_Object<T>::check_ruby_type(VALUE value)
40
56
  {
@@ -65,20 +81,7 @@ namespace Rice
65
81
  }
66
82
  else
67
83
  {
68
- return detail::unwrap<T>(this->value(), Data_Type<T>::ruby_data_type());
69
- }
70
- }
71
-
72
- template<typename T>
73
- inline T* Data_Object<T>::from_ruby(VALUE value)
74
- {
75
- if (Data_Type<T>::is_descendant(value))
76
- {
77
- return detail::unwrap<T>(value, Data_Type<T>::ruby_data_type());
78
- }
79
- else
80
- {
81
- throw create_type_exception<T>(value);
84
+ return detail::unwrap<T>(this->value(), Data_Type<T>::ruby_data_type(), false);
82
85
  }
83
86
  }
84
87
  }
@@ -88,8 +91,19 @@ namespace Rice::detail
88
91
  template<typename T>
89
92
  class To_Ruby
90
93
  {
94
+ static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
95
+ "Data_Object cannot be used with fundamental types");
96
+
97
+ static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
98
+ !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
99
+ !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
100
+ !std::is_same_v<T, std::set<T>> && !std::is_same_v<T, std::string> &&
101
+ !std::is_same_v<T, std::vector<T>>,
102
+ "Please include rice/stl.hpp header for STL support");
103
+
91
104
  public:
92
- VALUE convert(T& data)
105
+ template<typename U>
106
+ VALUE convert(U& data)
93
107
  {
94
108
  // Get the ruby typeinfo
95
109
  std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
@@ -99,10 +113,11 @@ namespace Rice::detail
99
113
  return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
100
114
  }
101
115
 
102
- VALUE convert(const T& data)
116
+ template<typename U>
117
+ VALUE convert(U&& data)
103
118
  {
104
119
  // Get the ruby typeinfo
105
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
120
+ std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
106
121
 
107
122
  // We always take ownership of data passed by value (yes the parameter is T& but the template
108
123
  // matched <typename T> thus we have to tell wrap to copy the reference we are sending to it
@@ -113,6 +128,16 @@ namespace Rice::detail
113
128
  template <typename T>
114
129
  class To_Ruby<T&>
115
130
  {
131
+ static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
132
+ "Data_Object cannot be used with fundamental types");
133
+
134
+ static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
135
+ !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
136
+ !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
137
+ !std::is_same_v<T, std::set<T>> && !std::is_same_v<T, std::string> &&
138
+ !std::is_same_v<T, std::vector<T>>,
139
+ "Please include rice/stl.hpp header for STL support");
140
+
116
141
  public:
117
142
  To_Ruby() = default;
118
143
 
@@ -120,26 +145,16 @@ namespace Rice::detail
120
145
  {
121
146
  }
122
147
 
123
- VALUE convert(T& data)
124
- {
125
- // Note that T could be a pointer or reference to a base class while data is in fact a
126
- // child class. Lookup the correct type so we return an instance of the correct Ruby class
127
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
128
-
129
- bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
130
- return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
131
- }
132
-
133
- VALUE convert(const T& data)
148
+ template<typename U>
149
+ VALUE convert(U& data)
134
150
  {
135
151
  // Note that T could be a pointer or reference to a base class while data is in fact a
136
152
  // child class. Lookup the correct type so we return an instance of the correct Ruby class
137
153
  std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
138
154
 
139
- bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
155
+ bool isOwner = (this->returnInfo_ && this->returnInfo_->isOwner());
140
156
  return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
141
157
  }
142
-
143
158
  private:
144
159
  Return* returnInfo_ = nullptr;
145
160
  };
@@ -147,6 +162,16 @@ namespace Rice::detail
147
162
  template <typename T>
148
163
  class To_Ruby<T*>
149
164
  {
165
+ static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
166
+ "Data_Object cannot be used with fundamental types");
167
+
168
+ static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
169
+ !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
170
+ !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
171
+ !std::is_same_v<T, std::set<T>> && !std::is_same_v<T, std::string> &&
172
+ !std::is_same_v<T, std::vector<T>>,
173
+ "Please include rice/stl.hpp header for STL support");
174
+
150
175
  public:
151
176
  To_Ruby() = default;
152
177
 
@@ -154,38 +179,31 @@ namespace Rice::detail
154
179
  {
155
180
  }
156
181
 
157
- VALUE convert(T* data)
182
+ template<typename U>
183
+ VALUE convert(U* data)
158
184
  {
159
- if (data)
185
+ bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
186
+
187
+ if (data == nullptr)
160
188
  {
161
- // Note that T could be a pointer or reference to a base class while data is in fact a
162
- // child class. Lookup the correct type so we return an instance of the correct Ruby class
163
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType(*data);
164
- bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
165
- return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
189
+ return Qnil;
166
190
  }
167
- else
191
+ else if (this->returnInfo_ && this->returnInfo_->isArray())
168
192
  {
169
- return Qnil;
193
+ using Buffer_T = Buffer<T>;
194
+ Buffer_T buffer((T*)data);
195
+ buffer.setOwner(isOwner);
196
+ return detail::wrap(Data_Type<Buffer_T>::klass(), Data_Type<Buffer_T>::ruby_data_type(), buffer, true);
170
197
  }
171
- }
172
-
173
- VALUE convert(const T* data)
174
- {
175
- if (data)
198
+ else
176
199
  {
177
200
  // Note that T could be a pointer or reference to a base class while data is in fact a
178
201
  // child class. Lookup the correct type so we return an instance of the correct Ruby class
179
202
  std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType(*data);
180
- bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
181
203
  return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
182
204
  }
183
- else
184
- {
185
- return Qnil;
186
- }
187
205
  }
188
-
206
+
189
207
  private:
190
208
  Return* returnInfo_ = nullptr;
191
209
  };
@@ -193,6 +211,16 @@ namespace Rice::detail
193
211
  template <typename T>
194
212
  class To_Ruby<T*&>
195
213
  {
214
+ static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
215
+ "Data_Object cannot be used with fundamental types");
216
+
217
+ static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
218
+ !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
219
+ !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
220
+ !std::is_same_v<T, std::set<T>> && !std::is_same_v<T, std::string> &&
221
+ !std::is_same_v<T, std::vector<T>>,
222
+ "Please include rice/stl.hpp header for STL support");
223
+
196
224
  public:
197
225
  To_Ruby() = default;
198
226
 
@@ -200,31 +228,65 @@ namespace Rice::detail
200
228
  {
201
229
  }
202
230
 
203
- VALUE convert(T* data)
231
+ template<typename U>
232
+ VALUE convert(U* data)
204
233
  {
205
- if (data)
234
+ bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
235
+
236
+ if (data == nullptr)
237
+ {
238
+ return Qnil;
239
+ }
240
+ else if (this->returnInfo_ && this->returnInfo_->isArray())
241
+ {
242
+ using Buffer_T = Buffer<intrinsic_type<T>>;
243
+ Buffer_T buffer((T*)data);
244
+ buffer.setOwner(isOwner);
245
+ return detail::wrap(Data_Type<Buffer_T>::klass(), Data_Type<Buffer_T>::ruby_data_type(), buffer, true);
246
+ }
247
+ else
206
248
  {
207
249
  // Note that T could be a pointer or reference to a base class while data is in fact a
208
250
  // child class. Lookup the correct type so we return an instance of the correct Ruby class
209
251
  std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType(*data);
210
- bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
211
252
  return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
212
253
  }
213
- else
214
- {
215
- return Qnil;
216
- }
217
254
  }
218
255
 
219
- VALUE convert(const T* data)
256
+ private:
257
+ Return* returnInfo_ = nullptr;
258
+ };
259
+
260
+ template <typename T>
261
+ class To_Ruby<T**>
262
+ {
263
+ static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
264
+ "Data_Object cannot be used with fundamental types");
265
+
266
+ static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
267
+ !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
268
+ !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
269
+ !std::is_same_v<T, std::set<T>> && !std::is_same_v<T, std::string> &&
270
+ !std::is_same_v<T, std::vector<T>>,
271
+ "Please include rice/stl.hpp header for STL support");
272
+
273
+ public:
274
+ To_Ruby() = default;
275
+
276
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
277
+ {
278
+ }
279
+
280
+ template<typename U>
281
+ VALUE convert(U** data)
220
282
  {
221
283
  if (data)
222
284
  {
223
- // Note that T could be a pointer or reference to a base class while data is in fact a
224
- // child class. Lookup the correct type so we return an instance of the correct Ruby class
225
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType(*data);
226
285
  bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
227
- return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
286
+ Buffer<T*> buffer((T**)data);
287
+ buffer.setOwner(isOwner);
288
+ using Buffer_T = Buffer<intrinsic_type<T>*>;
289
+ return detail::wrap(Data_Type<Buffer_T>::klass(), Data_Type<Buffer_T>::ruby_data_type(), buffer, true);
228
290
  }
229
291
  else
230
292
  {
@@ -251,6 +313,14 @@ namespace Rice::detail
251
313
  {
252
314
  static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
253
315
  "Data_Object cannot be used with fundamental types");
316
+
317
+ static_assert(!std::is_same_v<T, std::map<T, T>> || !std::is_same_v<T, std::unordered_map<T, T>> ||
318
+ !std::is_same_v<T, std::monostate> || !std::is_same_v<T, std::multimap<T, T>> ||
319
+ !std::is_same_v<T, std::optional<T>> || !std::is_same_v<T, std::pair<T, T>> ||
320
+ !std::is_same_v<T, std::set<T>> || !std::is_same_v<T, std::string> ||
321
+ !std::is_same_v<T, std::vector<T>>,
322
+ "Please include rice/stl.hpp header for STL support");
323
+
254
324
  public:
255
325
  From_Ruby() = default;
256
326
 
@@ -258,23 +328,30 @@ namespace Rice::detail
258
328
  {
259
329
  }
260
330
 
261
- bool is_convertible(VALUE value)
331
+ Convertible is_convertible(VALUE value)
262
332
  {
263
- return rb_type(value) == RUBY_T_DATA &&
264
- Data_Type<T>::is_descendant(value);
333
+ switch (rb_type(value))
334
+ {
335
+ case RUBY_T_DATA:
336
+ return Data_Type<T>::is_descendant(value) ? Convertible::Exact : Convertible::None;
337
+ break;
338
+ default:
339
+ return Convertible::None;
340
+ }
265
341
  }
266
342
 
267
343
  T convert(VALUE value)
268
344
  {
269
345
  using Intrinsic_T = intrinsic_type<T>;
346
+ Intrinsic_T* instance = detail::unwrap<Intrinsic_T>(value, Data_Type<Intrinsic_T>::ruby_data_type(), this->arg_ && this->arg_->isOwner());
270
347
 
271
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
348
+ if constexpr (std::is_constructible_v<T, T> && !std::is_convertible_v<T, T>)
272
349
  {
273
- return this->arg_->template defaultValue<Intrinsic_T>();
350
+ return T(*instance);
274
351
  }
275
352
  else
276
353
  {
277
- return *Data_Object<Intrinsic_T>::from_ruby(value);
354
+ return *instance;
278
355
  }
279
356
  }
280
357
 
@@ -287,6 +364,14 @@ namespace Rice::detail
287
364
  {
288
365
  static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
289
366
  "Data_Object cannot be used with fundamental types");
367
+
368
+ static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
369
+ !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
370
+ !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
371
+ !std::is_same_v<T, std::set<T>> && !std::is_same_v<T, std::string> &&
372
+ !std::is_same_v<T, std::vector<T>>,
373
+ "Please include rice/stl.hpp header for STL support");
374
+
290
375
  public:
291
376
  From_Ruby() = default;
292
377
 
@@ -294,55 +379,154 @@ namespace Rice::detail
294
379
  {
295
380
  }
296
381
 
297
- bool is_convertible(VALUE value)
382
+ Convertible is_convertible(VALUE value)
298
383
  {
299
- return rb_type(value) == RUBY_T_DATA &&
300
- Data_Type<T>::is_descendant(value);
384
+ switch (rb_type(value))
385
+ {
386
+ case RUBY_T_DATA:
387
+ return Data_Type<T>::is_descendant(value) ? Convertible::Exact : Convertible::None;
388
+ break;
389
+ default:
390
+ return Convertible::None;
391
+ }
301
392
  }
302
393
 
303
394
  T& convert(VALUE value)
304
395
  {
305
396
  using Intrinsic_T = intrinsic_type<T>;
306
397
 
307
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
308
- {
309
- return this->arg_->template defaultValue<Intrinsic_T>();
310
- }
311
- else
398
+ return *detail::unwrap<Intrinsic_T>(value, Data_Type<Intrinsic_T>::ruby_data_type(), this->arg_ && this->arg_->isOwner());
399
+ }
400
+
401
+ private:
402
+ Arg* arg_ = nullptr;
403
+ };
404
+
405
+ template<typename T>
406
+ class From_Ruby<T&&>
407
+ {
408
+ static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
409
+ "Data_Object cannot be used with fundamental types");
410
+
411
+ static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
412
+ !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
413
+ !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
414
+ !std::is_same_v<T, std::set<T>> && !std::is_same_v<T, std::string> &&
415
+ !std::is_same_v<T, std::vector<T>>,
416
+ "Please include rice/stl.hpp header for STL support");
417
+
418
+ public:
419
+ From_Ruby() = default;
420
+
421
+ explicit From_Ruby(Arg * arg) : arg_(arg)
422
+ {
423
+ }
424
+
425
+ Convertible is_convertible(VALUE value)
426
+ {
427
+ switch (rb_type(value))
312
428
  {
313
- return *Data_Object<Intrinsic_T>::from_ruby(value);
429
+ case RUBY_T_DATA:
430
+ return Data_Type<T>::is_descendant(value) ? Convertible::Exact : Convertible::None;
431
+ break;
432
+ default:
433
+ return Convertible::None;
314
434
  }
315
435
  }
316
436
 
437
+ T&& convert(VALUE value)
438
+ {
439
+ using Intrinsic_T = intrinsic_type<T>;
440
+
441
+ Intrinsic_T* object = detail::unwrap<Intrinsic_T>(value, Data_Type<Intrinsic_T>::ruby_data_type(), this->arg_ && this->arg_->isOwner());
442
+ return std::move(*object);
443
+ }
444
+
317
445
  private:
318
446
  Arg* arg_ = nullptr;
319
447
  };
320
448
 
449
+ // 99% of the time a T* represents a wrapped C++ object that we want to call methods on. However, T*
450
+ // could also be a pointer to an array of T objects, so T[]. OpenCV for example has API calls like this.
451
+ // In that case, the Ruby VALUE will be a Buffer<T> instance
321
452
  template<typename T>
322
453
  class From_Ruby<T*>
323
454
  {
324
455
  static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
325
456
  "Data_Object cannot be used with fundamental types");
457
+
458
+ static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
459
+ !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
460
+ !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
461
+ !std::is_same_v<T, std::set<T>> && !std::is_same_v<T, std::string> &&
462
+ !std::is_same_v<T, std::vector<T>>,
463
+ "Please include rice/stl.hpp header for STL support");
464
+
465
+ using Intrinsic_T = intrinsic_type<T>;
466
+
326
467
  public:
327
- bool is_convertible(VALUE value)
468
+ From_Ruby() = default;
469
+
470
+ explicit From_Ruby(Arg* arg) : arg_(arg)
328
471
  {
329
- return rb_type(value) == RUBY_T_DATA &&
330
- Data_Type<T>::is_descendant(value);
331
472
  }
332
473
 
333
- T* convert(VALUE value)
474
+ Convertible is_convertible(VALUE value)
334
475
  {
335
- using Intrinsic_T = intrinsic_type<T>;
336
-
337
- if (value == Qnil)
476
+ switch (rb_type(value))
338
477
  {
339
- return nullptr;
478
+ case RUBY_T_DATA:
479
+ if (this->arg_ && this->arg_->isArray())
480
+ {
481
+ return Data_Type<Buffer<T>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
482
+ }
483
+ else
484
+ {
485
+ return Data_Type<T>::is_descendant(value) ? Convertible::Exact : Convertible::None;
486
+ }
487
+ break;
488
+ case RUBY_T_NIL:
489
+ return Convertible::Exact;
490
+ break;
491
+ case RUBY_T_ARRAY:
492
+ return Convertible::Exact;
493
+ break;
494
+ default:
495
+ return Convertible::None;
340
496
  }
341
- else
497
+ }
498
+
499
+ T* convert(VALUE value)
500
+ {
501
+ switch (rb_type(value))
342
502
  {
343
- return Data_Object<Intrinsic_T>::from_ruby(value);
503
+ case RUBY_T_NIL:
504
+ {
505
+ return nullptr;
506
+ break;
507
+ }
508
+ case RUBY_T_DATA:
509
+ {
510
+ if (this->arg_ && this->arg_->isArray())
511
+ {
512
+ using Buffer_T = Buffer<Intrinsic_T>;
513
+ Buffer_T* buffer = detail::unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), this->arg_ && this->arg_->isOwner());
514
+ return buffer->ptr();
515
+ }
516
+ else
517
+ {
518
+ return detail::unwrap<Intrinsic_T>(value, Data_Type<Intrinsic_T>::ruby_data_type(), this->arg_ && this->arg_->isOwner());
519
+ }
520
+ }
521
+ default:
522
+ {
523
+ throw create_type_exception<Intrinsic_T>(value);
524
+ }
344
525
  }
345
526
  }
527
+
528
+ private:
529
+ Arg* arg_ = nullptr;
346
530
  };
347
531
 
348
532
  template<typename T>
@@ -350,11 +534,31 @@ namespace Rice::detail
350
534
  {
351
535
  static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
352
536
  "Data_Object cannot be used with fundamental types");
537
+
538
+ static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
539
+ !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
540
+ !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
541
+ !std::is_same_v<T, std::set<T>> && !std::is_same_v<T, std::string> &&
542
+ !std::is_same_v<T, std::vector<T>>,
543
+ "Please include rice/stl.hpp header for STL support");
544
+
353
545
  public:
354
- bool is_convertible(VALUE value)
546
+ From_Ruby() = default;
547
+
548
+ explicit From_Ruby(Arg* arg) : arg_(arg)
549
+ {
550
+ }
551
+
552
+ Convertible is_convertible(VALUE value)
355
553
  {
356
- return rb_type(value) == RUBY_T_DATA &&
357
- Data_Type<T>::is_descendant(value);
554
+ switch (rb_type(value))
555
+ {
556
+ case RUBY_T_DATA:
557
+ return Data_Type<T>::is_descendant(value) ? Convertible::Exact : Convertible::None;
558
+ break;
559
+ default:
560
+ return Convertible::None;
561
+ }
358
562
  }
359
563
 
360
564
  T* convert(VALUE value)
@@ -367,9 +571,78 @@ namespace Rice::detail
367
571
  }
368
572
  else
369
573
  {
370
- return Data_Object<Intrinsic_T>::from_ruby(value);
574
+ return detail::unwrap<Intrinsic_T>(value, Data_Type<Intrinsic_T>::ruby_data_type(), this->arg_ && this->arg_->isOwner());
575
+ }
576
+ }
577
+
578
+ private:
579
+ Arg* arg_ = nullptr;
580
+ };
581
+
582
+ template<typename T>
583
+ class From_Ruby<T**>
584
+ {
585
+ static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
586
+ "Data_Object cannot be used with fundamental types");
587
+
588
+ static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
589
+ !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
590
+ !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
591
+ !std::is_same_v<T, std::set<T>> && !std::is_same_v<T, std::string> &&
592
+ !std::is_same_v<T, std::vector<T>>,
593
+ "Please include rice/stl.hpp header for STL support");
594
+
595
+ using Intrinsic_T = intrinsic_type<T>;
596
+ public:
597
+ From_Ruby() = default;
598
+
599
+ explicit From_Ruby(Arg* arg) : arg_(arg)
600
+ {
601
+ }
602
+
603
+ Convertible is_convertible(VALUE value)
604
+ {
605
+ switch (rb_type(value))
606
+ {
607
+ case RUBY_T_DATA:
608
+ return Data_Type<Buffer<T*>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
609
+ break;
610
+ case RUBY_T_NIL:
611
+ return Convertible::Exact;
612
+ break;
613
+ case RUBY_T_ARRAY:
614
+ return Convertible::Exact;
615
+ break;
616
+ default:
617
+ return Convertible::None;
618
+ }
619
+ }
620
+
621
+ T** convert(VALUE value)
622
+ {
623
+ switch (rb_type(value))
624
+ {
625
+ case RUBY_T_DATA:
626
+ {
627
+ Buffer<Intrinsic_T*>* buffer = detail::unwrap<Buffer<Intrinsic_T*>>(value, Data_Type<Buffer<Intrinsic_T*>>::ruby_data_type(), false);
628
+ return buffer->ptr();
629
+ break;
630
+ }
631
+ case RUBY_T_NIL:
632
+ {
633
+ return nullptr;
634
+ break;
635
+ }
636
+ default:
637
+ {
638
+ throw create_type_exception<Intrinsic_T>(value);
639
+ }
371
640
  }
372
641
  }
642
+
643
+ private:
644
+ Arg* arg_ = nullptr;
645
+ std::vector<Intrinsic_T*> vector_;
373
646
  };
374
647
 
375
648
  template<typename T>
@@ -377,11 +650,30 @@ namespace Rice::detail
377
650
  {
378
651
  static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
379
652
  "Data_Object cannot be used with fundamental types");
653
+
654
+ static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
655
+ !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
656
+ !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
657
+ !std::is_same_v<T, std::set<T>> && !std::is_same_v<T, std::string> &&
658
+ !std::is_same_v<T, std::vector<T>>,
659
+ "Please include rice/stl.hpp header for STL support");
660
+
380
661
  public:
662
+ Convertible is_convertible(VALUE value)
663
+ {
664
+ switch (rb_type(value))
665
+ {
666
+ case RUBY_T_DATA:
667
+ return Data_Type<T>::is_descendant(value) ? Convertible::Exact : Convertible::None;
668
+ break;
669
+ default:
670
+ return Convertible::None;
671
+ }
672
+ }
673
+
381
674
  static Data_Object<T> convert(VALUE value)
382
675
  {
383
676
  return Data_Object<T>(value);
384
677
  }
385
678
  };
386
679
  }
387
- #endif // Rice__Data_Object__ipp_