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
@@ -1,110 +1,276 @@
1
- #ifndef Rice__detail__from_ruby__ipp_
2
- #define Rice__detail__from_ruby__ipp_
3
-
1
+ #include <limits>
4
2
  #include <optional>
5
3
  #include <stdexcept>
6
- #include "../Exception_defn.hpp"
7
- #include "../Arg.hpp"
8
- #include "RubyFunction.hpp"
9
4
 
10
5
  /* This file implements conversions from Ruby to native values fo fundamental types
11
6
  such as bool, int, float, etc. It also includes conversions for chars and strings */
12
7
  namespace Rice::detail
13
8
  {
14
- // =========== short ============
15
- template<>
16
- class From_Ruby<short>
9
+ inline Convertible operator&(Convertible left, Convertible right)
10
+ {
11
+ return static_cast<Convertible>(static_cast<uint8_t>(left) & static_cast<uint8_t>(right));
12
+ }
13
+
14
+ inline Convertible operator|(Convertible left, Convertible right)
15
+ {
16
+ return static_cast<Convertible>(static_cast<uint8_t>(left) | static_cast<uint8_t>(right));
17
+ }
18
+
19
+ inline bool operator<(Convertible left, Convertible right)
20
+ {
21
+ return static_cast<uint8_t>(left) < static_cast<uint8_t>(right);
22
+ }
23
+
24
+ // =========== Helpers ============
25
+ template<typename T>
26
+ class FromRubyFundamental
17
27
  {
18
28
  public:
19
- From_Ruby() = default;
29
+ using RubyType_T = RubyType<T>;
20
30
 
21
- explicit From_Ruby(Arg* arg) : arg_(arg)
31
+ static Convertible is_convertible(VALUE value)
22
32
  {
33
+ ruby_value_type valueType = rb_type(value);
34
+
35
+ if (RubyType_T::Exact.find(valueType) != RubyType_T::Exact.end())
36
+ {
37
+ return Convertible::Exact;
38
+ }
39
+ else if (RubyType_T::Castable.find(valueType) != RubyType_T::Castable.end())
40
+ {
41
+ return Convertible::Cast;
42
+ }
43
+ else if (RubyType_T::Narrowable.find(valueType) != RubyType_T::Narrowable.end())
44
+ {
45
+ return Convertible::Narrow;
46
+ }
47
+ else
48
+ {
49
+ return Convertible::None;
50
+ }
23
51
  }
24
52
 
25
- bool is_convertible(VALUE value)
53
+ static T convert(VALUE value)
26
54
  {
27
- return rb_type(value) == RUBY_T_FIXNUM;
55
+ return (T)protect(RubyType_T::fromRuby, value);
28
56
  }
57
+ };
29
58
 
30
- short convert(VALUE value)
59
+ template<typename T>
60
+ class FromRubyFundamental<T*>
61
+ {
62
+ public:
63
+ static Convertible is_convertible(VALUE value)
31
64
  {
32
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
65
+ ruby_value_type valueType = rb_type(value);
66
+
67
+ switch (valueType)
33
68
  {
34
- return this->arg_->defaultValue<short>();
69
+ case RUBY_T_NIL:
70
+ {
71
+ return Convertible::Exact;
72
+ break;
73
+ }
74
+ case RUBY_T_DATA:
75
+ {
76
+ return Data_Type<Buffer<T>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
77
+ }
78
+ default:
79
+ {
80
+ return Convertible::None;
81
+ }
35
82
  }
36
- else
83
+ }
84
+
85
+ static T* convert(VALUE value, Arg* arg)
86
+ {
87
+ ruby_value_type valueType = rb_type(value);
88
+
89
+ switch (valueType)
37
90
  {
38
- return protect(rb_num2short_inline, value);
91
+ case RUBY_T_NIL:
92
+ {
93
+ return nullptr;
94
+ }
95
+ case RUBY_T_DATA:
96
+ {
97
+ if (Data_Type<Buffer<T>>::is_descendant(value))
98
+ {
99
+ Buffer<T>* buffer = unwrap<Buffer<T>>(value, Data_Type<Buffer<T>>::ruby_data_type(), false);
100
+ if (arg && arg->isOwner())
101
+ {
102
+ buffer->release();
103
+ }
104
+ return buffer->ptr();
105
+ }
106
+ [[fallthrough]];
107
+ }
108
+ default:
109
+ {
110
+ std::string name = typeName(typeid(Buffer<intrinsic_type<T>>));
111
+ std::string expected = rubyClassName(name);
112
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
113
+ detail::protect(rb_obj_classname, value), expected.c_str());
114
+ }
39
115
  }
40
116
  }
41
-
117
+ };
118
+
119
+ template<typename T>
120
+ class FromRubyFundamental<T**>
121
+ {
122
+ public:
123
+ static Convertible is_convertible(VALUE value)
124
+ {
125
+ ruby_value_type valueType = rb_type(value);
126
+
127
+ switch (valueType)
128
+ {
129
+ case RUBY_T_NIL:
130
+ {
131
+ return Convertible::Exact;
132
+ break;
133
+ }
134
+ case RUBY_T_DATA:
135
+ {
136
+ return Data_Type<Buffer<T*>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
137
+ }
138
+ default:
139
+ {
140
+ return Convertible::None;
141
+ }
142
+ }
143
+ }
144
+
145
+ static T** convert(VALUE value, Arg* arg)
146
+ {
147
+ ruby_value_type valueType = rb_type(value);
148
+
149
+ switch (valueType)
150
+ {
151
+ case RUBY_T_NIL:
152
+ {
153
+ return nullptr;
154
+ }
155
+ case RUBY_T_DATA:
156
+ {
157
+ if (Data_Type<Buffer<T*>>::is_descendant(value))
158
+ {
159
+ Buffer<T*>* buffer = unwrap<Buffer<T*>>(value, Data_Type<Buffer<T*>>::ruby_data_type(), false);
160
+ if (arg && arg->isOwner())
161
+ {
162
+ buffer->release();
163
+ }
164
+ return buffer->ptr();
165
+ }
166
+ [[fallthrough]];
167
+ }
168
+ default:
169
+ {
170
+ std::string name = typeName(typeid(Buffer<intrinsic_type<T>*>));
171
+ std::string expected = rubyClassName(name);
172
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
173
+ detail::protect(rb_obj_classname, value), expected.c_str());
174
+ }
175
+ }
176
+ }
177
+ };
178
+
179
+ // =========== bool ============
180
+ template<>
181
+ class From_Ruby<bool>
182
+ {
183
+ public:
184
+ From_Ruby() = default;
185
+
186
+ explicit From_Ruby(Arg* arg) : arg_(arg)
187
+ {
188
+ }
189
+
190
+ Convertible is_convertible(VALUE value)
191
+ {
192
+ return FromRubyFundamental<bool>::is_convertible(value);
193
+ }
194
+
195
+ bool convert(VALUE value)
196
+ {
197
+ return FromRubyFundamental<bool>::convert(value);
198
+ }
199
+
42
200
  private:
43
201
  Arg* arg_ = nullptr;
44
202
  };
45
203
 
46
204
  template<>
47
- class From_Ruby<short&>
205
+ class From_Ruby<bool&>
48
206
  {
49
207
  public:
208
+ using Buffer_T = Buffer<bool>;
209
+
50
210
  From_Ruby() = default;
51
211
 
52
212
  explicit From_Ruby(Arg* arg) : arg_(arg)
53
213
  {
54
214
  }
55
215
 
56
- bool is_convertible(VALUE value)
216
+ Convertible is_convertible(VALUE value)
57
217
  {
58
- return rb_type(value) == RUBY_T_FIXNUM;
218
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
219
+ {
220
+ return Convertible::Exact;
221
+ }
222
+ else
223
+ {
224
+ return FromRubyFundamental<bool>::is_convertible(value);
225
+ }
59
226
  }
60
227
 
61
- short& convert(VALUE value)
228
+ bool& convert(VALUE value)
62
229
  {
63
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
230
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
64
231
  {
65
- return this->arg_->defaultValue<short>();
232
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
233
+ return buffer->reference();
66
234
  }
67
235
  else
68
236
  {
69
- this->converted_ = protect(rb_num2short_inline, value);
237
+ this->converted_ = FromRubyFundamental<bool>::convert(value);
70
238
  return this->converted_;
71
239
  }
72
240
  }
73
241
 
74
242
  private:
75
243
  Arg* arg_ = nullptr;
76
- short converted_ = 0;
244
+ bool converted_ = false;
77
245
  };
78
246
 
79
247
  template<>
80
- class From_Ruby<short*>
248
+ class From_Ruby<bool*>
81
249
  {
82
250
  public:
83
- bool is_convertible(VALUE value)
251
+ From_Ruby() = default;
252
+
253
+ explicit From_Ruby(Arg* arg) : arg_(arg)
84
254
  {
85
- return rb_type(value) == RUBY_T_FIXNUM;
86
255
  }
87
256
 
88
- short* convert(VALUE value)
257
+ Convertible is_convertible(VALUE value)
89
258
  {
90
- if (value == Qnil)
91
- {
92
- return nullptr;
93
- }
94
- else
95
- {
96
- this->converted_ = protect(rb_num2short_inline, value);
97
- return &this->converted_;
98
- }
259
+ return FromRubyFundamental<bool>::is_convertible(value);
260
+ }
261
+
262
+ bool* convert(VALUE value)
263
+ {
264
+ return FromRubyFundamental<bool*>::convert(value, this->arg_);
99
265
  }
100
266
 
101
267
  private:
102
- short converted_ = 0;
268
+ Arg* arg_ = nullptr;
103
269
  };
104
270
 
105
- // =========== int ============
271
+ // =========== char ============
106
272
  template<>
107
- class From_Ruby<int>
273
+ class From_Ruby<char>
108
274
  {
109
275
  public:
110
276
  From_Ruby() = default;
@@ -113,29 +279,65 @@ namespace Rice::detail
113
279
  {
114
280
  }
115
281
 
116
- bool is_convertible(VALUE value)
282
+ Convertible is_convertible(VALUE value)
117
283
  {
118
- return rb_type(value) == RUBY_T_FIXNUM;
284
+ return FromRubyFundamental<char>::is_convertible(value);
119
285
  }
120
286
 
121
- int convert(VALUE value)
287
+ char convert(VALUE value)
288
+ {
289
+ return FromRubyFundamental<char>::convert(value);
290
+ }
291
+
292
+ private:
293
+ Arg* arg_ = nullptr;
294
+ };
295
+
296
+ template<>
297
+ class From_Ruby<char&>
298
+ {
299
+ public:
300
+ using Buffer_T = Buffer<char>;
301
+
302
+ From_Ruby() = default;
303
+
304
+ explicit From_Ruby(Arg* arg) : arg_(arg)
305
+ {
306
+ }
307
+
308
+ Convertible is_convertible(VALUE value)
122
309
  {
123
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
310
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
124
311
  {
125
- return this->arg_->defaultValue<int>();
312
+ return Convertible::Exact;
126
313
  }
127
314
  else
128
315
  {
129
- return (int)protect(rb_num2long_inline, value);
316
+ return FromRubyFundamental<char>::is_convertible(value);
130
317
  }
131
318
  }
132
-
319
+
320
+ char& convert(VALUE value)
321
+ {
322
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
323
+ {
324
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
325
+ return buffer->reference();
326
+ }
327
+ else
328
+ {
329
+ this->converted_ = FromRubyFundamental<char>::convert(value);
330
+ return this->converted_;
331
+ }
332
+ }
333
+
133
334
  private:
134
335
  Arg* arg_ = nullptr;
336
+ char converted_ = 0;
135
337
  };
136
338
 
137
339
  template<>
138
- class From_Ruby<int&>
340
+ class From_Ruby<char*>
139
341
  {
140
342
  public:
141
343
  From_Ruby() = default;
@@ -144,58 +346,567 @@ namespace Rice::detail
144
346
  {
145
347
  }
146
348
 
147
- bool is_convertible(VALUE value)
349
+ Convertible is_convertible(VALUE value)
148
350
  {
149
- return rb_type(value) == RUBY_T_FIXNUM;
351
+ switch (rb_type(value))
352
+ {
353
+ case RUBY_T_NIL:
354
+ {
355
+ return Convertible::Exact;
356
+ }
357
+ case RUBY_T_STRING:
358
+ {
359
+ return Convertible::Exact;
360
+ }
361
+ default:
362
+ {
363
+ return FromRubyFundamental<char*>::is_convertible(value);
364
+ }
365
+ }
150
366
  }
151
367
 
152
- int& convert(VALUE value)
368
+ char* convert(VALUE value)
153
369
  {
154
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
370
+ switch (rb_type(value))
155
371
  {
156
- return this->arg_->defaultValue<int>();
372
+ case RUBY_T_NIL:
373
+ {
374
+ return nullptr;
375
+ }
376
+ case RUBY_T_STRING:
377
+ {
378
+ // WARNING - this shares the Ruby string memory directly with C++. value really should be frozen.
379
+ // Maybe we should enforce that? Note the user can always create a Buffer to allocate new memory.
380
+ return rb_string_value_cstr(&value);
381
+ }
382
+ default:
383
+ {
384
+ char* rb_string_value_cstr(volatile VALUE * ptr);
385
+ return FromRubyFundamental<char*>::convert(value, this->arg_);
386
+ }
157
387
  }
158
- else
388
+ }
389
+
390
+ private:
391
+ Arg* arg_ = nullptr;
392
+ };
393
+
394
+ template<>
395
+ class From_Ruby<const char*> : public From_Ruby<char*>
396
+ {
397
+ };
398
+
399
+ template<>
400
+ class From_Ruby<char**>
401
+ {
402
+ public:
403
+ From_Ruby() = default;
404
+
405
+ explicit From_Ruby(Arg* arg) : arg_(arg)
406
+ {
407
+ if (this->arg_ && this->arg_->isOwner())
159
408
  {
160
- this->converted_ = (int)protect(rb_num2long_inline, value);
161
- return this->converted_;
409
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
162
410
  }
163
411
  }
164
412
 
413
+ Convertible is_convertible(VALUE value)
414
+ {
415
+ return FromRubyFundamental<char**>::is_convertible(value);
416
+ }
417
+
418
+ char** convert(VALUE value)
419
+ {
420
+ return FromRubyFundamental<char**>::convert(value, this->arg_);
421
+ }
422
+
165
423
  private:
166
424
  Arg* arg_ = nullptr;
167
- int converted_ = 0;
168
425
  };
169
426
 
427
+ // =========== unsigned char ============
170
428
  template<>
171
- class From_Ruby<int*>
429
+ class From_Ruby<unsigned char>
172
430
  {
173
431
  public:
174
- bool is_convertible(VALUE value)
432
+ From_Ruby() = default;
433
+
434
+ explicit From_Ruby(Arg* arg) : arg_(arg)
175
435
  {
176
- return rb_type(value) == RUBY_T_FIXNUM;
177
436
  }
178
437
 
179
- int* convert(VALUE value)
438
+ Convertible is_convertible(VALUE value)
180
439
  {
181
- if (value == Qnil)
440
+ return FromRubyFundamental<unsigned char>::is_convertible(value);
441
+ }
442
+
443
+ unsigned char convert(VALUE value)
444
+ {
445
+ return FromRubyFundamental<unsigned char>::convert(value);
446
+ }
447
+
448
+ private:
449
+ Arg* arg_ = nullptr;
450
+ };
451
+
452
+ template<>
453
+ class From_Ruby<unsigned char&>
454
+ {
455
+ public:
456
+ using Buffer_T = Buffer<unsigned char>;
457
+
458
+ From_Ruby() = default;
459
+
460
+ explicit From_Ruby(Arg* arg) : arg_(arg)
461
+ {
462
+ }
463
+
464
+ Convertible is_convertible(VALUE value)
465
+ {
466
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
182
467
  {
183
- return nullptr;
468
+ return Convertible::Exact;
469
+ }
470
+ else
471
+ {
472
+ return FromRubyFundamental<unsigned char>::is_convertible(value);
473
+ }
474
+ }
475
+
476
+ unsigned char& convert(VALUE value)
477
+ {
478
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
479
+ {
480
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
481
+ return buffer->reference();
184
482
  }
185
483
  else
186
484
  {
187
- this->converted_ = (int)protect(rb_num2long_inline, value);
188
- return &this->converted_;
485
+ this->converted_ = FromRubyFundamental<unsigned char>::convert(value);
486
+ return this->converted_;
189
487
  }
190
488
  }
191
489
 
192
490
  private:
193
- int converted_;
491
+ Arg* arg_ = nullptr;
492
+ unsigned char converted_ = 0;
194
493
  };
195
494
 
196
- // =========== long ============
197
495
  template<>
198
- class From_Ruby<long>
496
+ class From_Ruby<unsigned char*>
497
+ {
498
+ public:
499
+ From_Ruby() = default;
500
+
501
+ explicit From_Ruby(Arg* arg) : arg_(arg)
502
+ {
503
+ }
504
+
505
+ Convertible is_convertible(VALUE value)
506
+ {
507
+ return FromRubyFundamental<unsigned char*>::is_convertible(value);
508
+ }
509
+
510
+ unsigned char* convert(VALUE value)
511
+ {
512
+ return FromRubyFundamental<unsigned char*>::convert(value, this->arg_);
513
+ }
514
+
515
+ private:
516
+ Arg* arg_ = nullptr;
517
+ };
518
+
519
+ template<>
520
+ class From_Ruby<unsigned char**>
521
+ {
522
+ public:
523
+ From_Ruby() = default;
524
+
525
+ explicit From_Ruby(Arg* arg) : arg_(arg)
526
+ {
527
+ if (this->arg_ && this->arg_->isOwner())
528
+ {
529
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
530
+ }
531
+ }
532
+
533
+ Convertible is_convertible(VALUE value)
534
+ {
535
+ return FromRubyFundamental<unsigned char**>::is_convertible(value);
536
+ }
537
+
538
+ unsigned char** convert(VALUE value)
539
+ {
540
+ return FromRubyFundamental<unsigned char**>::convert(value, this->arg_);
541
+ }
542
+
543
+ private:
544
+ Arg* arg_ = nullptr;
545
+ };
546
+
547
+ // =========== signed char ============
548
+ template<>
549
+ class From_Ruby<signed char>
550
+ {
551
+ public:
552
+ From_Ruby() = default;
553
+
554
+ explicit From_Ruby(Arg* arg) : arg_(arg)
555
+ {
556
+ }
557
+
558
+ Convertible is_convertible(VALUE value)
559
+ {
560
+ return FromRubyFundamental<signed char>::is_convertible(value);
561
+ }
562
+
563
+ signed char convert(VALUE value)
564
+ {
565
+ return FromRubyFundamental<signed char>::convert(value);
566
+ }
567
+
568
+ private:
569
+ Arg* arg_ = nullptr;
570
+ };
571
+
572
+ template<>
573
+ class From_Ruby<signed char&>
574
+ {
575
+ public:
576
+ using Buffer_T = Buffer<signed char>;
577
+
578
+ From_Ruby() = default;
579
+
580
+ explicit From_Ruby(Arg* arg) : arg_(arg)
581
+ {
582
+ }
583
+
584
+ Convertible is_convertible(VALUE value)
585
+ {
586
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
587
+ {
588
+ return Convertible::Exact;
589
+ }
590
+ else
591
+ {
592
+ return FromRubyFundamental<signed char>::is_convertible(value);
593
+ }
594
+ }
595
+
596
+ signed char& convert(VALUE value)
597
+ {
598
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
599
+ {
600
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
601
+ return buffer->reference();
602
+ }
603
+ else
604
+ {
605
+ this->converted_ = FromRubyFundamental<signed char>::convert(value);
606
+ return this->converted_;
607
+ }
608
+ }
609
+
610
+ private:
611
+ Arg* arg_ = nullptr;
612
+ signed char converted_ = 0;
613
+ };
614
+
615
+ template<>
616
+ class From_Ruby<signed char*>
617
+ {
618
+ public:
619
+ From_Ruby() = default;
620
+
621
+ explicit From_Ruby(Arg* arg) : arg_(arg)
622
+ {
623
+ }
624
+
625
+ Convertible is_convertible(VALUE value)
626
+ {
627
+ return FromRubyFundamental<signed char*>::is_convertible(value);
628
+ }
629
+
630
+ signed char* convert(VALUE value)
631
+ {
632
+ return FromRubyFundamental<signed char*>::convert(value, this->arg_);
633
+ }
634
+
635
+ private:
636
+ Arg* arg_ = nullptr;
637
+ };
638
+
639
+ template<>
640
+ class From_Ruby<signed char**>
641
+ {
642
+ public:
643
+ From_Ruby() = default;
644
+
645
+ explicit From_Ruby(Arg* arg) : arg_(arg)
646
+ {
647
+ if (this->arg_ && this->arg_->isOwner())
648
+ {
649
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
650
+ }
651
+ }
652
+
653
+ Convertible is_convertible(VALUE value)
654
+ {
655
+ return FromRubyFundamental<signed char**>::is_convertible(value);
656
+ }
657
+
658
+ signed char** convert(VALUE value)
659
+ {
660
+ return FromRubyFundamental<signed char**>::convert(value, this->arg_);
661
+ }
662
+
663
+ private:
664
+ Arg* arg_ = nullptr;
665
+ };
666
+
667
+ // =========== double ============
668
+ template<>
669
+ class From_Ruby<double>
670
+ {
671
+ public:
672
+ From_Ruby() = default;
673
+
674
+ explicit From_Ruby(Arg* arg) : arg_(arg)
675
+ {
676
+ }
677
+
678
+ Convertible is_convertible(VALUE value)
679
+ {
680
+ return FromRubyFundamental<double>::is_convertible(value);
681
+ }
682
+
683
+ double convert(VALUE value)
684
+ {
685
+ return FromRubyFundamental<double>::convert(value);
686
+ }
687
+
688
+ private:
689
+ Arg* arg_ = nullptr;
690
+ };
691
+
692
+ template<>
693
+ class From_Ruby<double&>
694
+ {
695
+ public:
696
+ using Buffer_T = Buffer<double>;
697
+
698
+ From_Ruby() = default;
699
+
700
+ explicit From_Ruby(Arg* arg) : arg_(arg)
701
+ {
702
+ }
703
+
704
+ Convertible is_convertible(VALUE value)
705
+ {
706
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
707
+ {
708
+ return Convertible::Exact;
709
+ }
710
+ else
711
+ {
712
+ return FromRubyFundamental<double>::is_convertible(value);
713
+ }
714
+ }
715
+
716
+ double& convert(VALUE value)
717
+ {
718
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
719
+ {
720
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
721
+ return buffer->reference();
722
+ }
723
+ else
724
+ {
725
+ this->converted_ = FromRubyFundamental<double>::convert(value);
726
+ return this->converted_;
727
+ }
728
+ }
729
+
730
+ private:
731
+ Arg* arg_ = nullptr;
732
+ double converted_;
733
+ };
734
+
735
+ template<>
736
+ class From_Ruby<double*>
737
+ {
738
+ public:
739
+ From_Ruby() = default;
740
+
741
+ explicit From_Ruby(Arg* arg) : arg_(arg)
742
+ {
743
+ }
744
+
745
+ Convertible is_convertible(VALUE value)
746
+ {
747
+ return FromRubyFundamental<double*>::is_convertible(value);
748
+ }
749
+
750
+ double* convert(VALUE value)
751
+ {
752
+ return FromRubyFundamental<double*>::convert(value, this->arg_);
753
+ }
754
+
755
+ private:
756
+ Arg* arg_ = nullptr;
757
+ };
758
+
759
+ template<>
760
+ class From_Ruby<double**>
761
+ {
762
+ public:
763
+ From_Ruby() = default;
764
+
765
+ explicit From_Ruby(Arg* arg) : arg_(arg)
766
+ {
767
+ if (this->arg_ && this->arg_->isOwner())
768
+ {
769
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
770
+ }
771
+ }
772
+
773
+ Convertible is_convertible(VALUE value)
774
+ {
775
+ return FromRubyFundamental<double**>::is_convertible(value);
776
+ }
777
+
778
+ double** convert(VALUE value)
779
+ {
780
+ return FromRubyFundamental<double**>::convert(value, this->arg_);
781
+ }
782
+
783
+ private:
784
+ Arg* arg_ = nullptr;
785
+ };
786
+
787
+ // =========== float ============
788
+ template<>
789
+ class From_Ruby<float>
790
+ {
791
+ public:
792
+ From_Ruby() = default;
793
+
794
+ explicit From_Ruby(Arg* arg) : arg_(arg)
795
+ {
796
+ }
797
+
798
+ Convertible is_convertible(VALUE value)
799
+ {
800
+ return FromRubyFundamental<float>::is_convertible(value);
801
+ }
802
+
803
+ float convert(VALUE value)
804
+ {
805
+ return FromRubyFundamental<float>::convert(value);
806
+ }
807
+
808
+ private:
809
+ Arg* arg_ = nullptr;
810
+ };
811
+
812
+ template<>
813
+ class From_Ruby<float&>
814
+ {
815
+ public:
816
+ using Buffer_T = Buffer<float>;
817
+
818
+ From_Ruby() = default;
819
+
820
+ explicit From_Ruby(Arg* arg) : arg_(arg)
821
+ {
822
+ }
823
+
824
+ Convertible is_convertible(VALUE value)
825
+ {
826
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
827
+ {
828
+ return Convertible::Exact;
829
+ }
830
+ else
831
+ {
832
+ return FromRubyFundamental<float>::is_convertible(value);
833
+ }
834
+ }
835
+
836
+ float& convert(VALUE value)
837
+ {
838
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
839
+ {
840
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
841
+ return buffer->reference();
842
+ }
843
+ else
844
+ {
845
+ this->converted_ = FromRubyFundamental<float>::convert(value);
846
+ return this->converted_;
847
+ }
848
+ }
849
+
850
+ private:
851
+ Arg* arg_ = nullptr;
852
+ float converted_;
853
+ };
854
+
855
+ template<>
856
+ class From_Ruby<float*>
857
+ {
858
+ public:
859
+ From_Ruby() = default;
860
+
861
+ explicit From_Ruby(Arg* arg) : arg_(arg)
862
+ {
863
+ }
864
+
865
+ Convertible is_convertible(VALUE value)
866
+ {
867
+ return FromRubyFundamental<float*>::is_convertible(value);
868
+ }
869
+
870
+ float* convert(VALUE value)
871
+ {
872
+ return FromRubyFundamental<float*>::convert(value, this->arg_);
873
+ }
874
+
875
+ private:
876
+ Arg* arg_ = nullptr;
877
+ };
878
+
879
+ template<>
880
+ class From_Ruby<float**>
881
+ {
882
+ public:
883
+ From_Ruby() = default;
884
+
885
+ explicit From_Ruby(Arg* arg) : arg_(arg)
886
+ {
887
+ if (this->arg_ && this->arg_->isOwner())
888
+ {
889
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
890
+ }
891
+ }
892
+
893
+ Convertible is_convertible(VALUE value)
894
+ {
895
+ return FromRubyFundamental<float**>::is_convertible(value);
896
+ }
897
+
898
+ float** convert(VALUE value)
899
+ {
900
+ return FromRubyFundamental<float**>::convert(value, this->arg_);
901
+ }
902
+
903
+ private:
904
+ Arg* arg_ = nullptr;
905
+ };
906
+
907
+ // =========== int ============
908
+ template<>
909
+ class From_Ruby<int>
199
910
  {
200
911
  public:
201
912
  From_Ruby() = default;
@@ -204,21 +915,25 @@ namespace Rice::detail
204
915
  {
205
916
  }
206
917
 
207
- bool is_convertible(VALUE value)
918
+ Convertible is_convertible(VALUE value)
208
919
  {
209
- return rb_type(value) == RUBY_T_FIXNUM;
210
- }
920
+ Convertible result = FromRubyFundamental<int>::is_convertible(value);
211
921
 
212
- long convert(VALUE value)
213
- {
214
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
215
- {
216
- return this->arg_->defaultValue<long>();
217
- }
218
- else
922
+ // Is this an enum? If so we want to support converting it to an integer
923
+ if (result == Convertible::None && rb_type(value) == RUBY_T_DATA)
219
924
  {
220
- return protect(rb_num2long_inline, value);
925
+ static ID id = protect(rb_intern, "to_int");
926
+ if (protect(rb_respond_to, value, id))
927
+ {
928
+ result = Convertible::Cast;
929
+ }
221
930
  }
931
+ return result;
932
+ }
933
+
934
+ int convert(VALUE value)
935
+ {
936
+ return FromRubyFundamental<int>::convert(value);
222
937
  }
223
938
 
224
939
  private:
@@ -226,98 +941,103 @@ namespace Rice::detail
226
941
  };
227
942
 
228
943
  template<>
229
- class From_Ruby<long&>
944
+ class From_Ruby<int&>
230
945
  {
231
946
  public:
947
+ using Buffer_T = Buffer<int>;
948
+
232
949
  From_Ruby() = default;
233
950
 
234
951
  explicit From_Ruby(Arg* arg) : arg_(arg)
235
952
  {
236
953
  }
237
954
 
238
- bool is_convertible(VALUE value)
955
+ Convertible is_convertible(VALUE value)
239
956
  {
240
- return rb_type(value) == RUBY_T_FIXNUM;
957
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
958
+ {
959
+ return Convertible::Exact;
960
+ }
961
+ else
962
+ {
963
+ return FromRubyFundamental<int>::is_convertible(value);
964
+ }
241
965
  }
242
966
 
243
- long& convert(VALUE value)
967
+ int& convert(VALUE value)
244
968
  {
245
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
969
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
246
970
  {
247
- return this->arg_->defaultValue<long>();
971
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
972
+ return buffer->reference();
248
973
  }
249
974
  else
250
975
  {
251
- this->converted_ = protect(rb_num2long_inline, value);
976
+ this->converted_ = FromRubyFundamental<int>::convert(value);
252
977
  return this->converted_;
253
978
  }
254
979
  }
255
980
 
256
981
  private:
257
982
  Arg* arg_ = nullptr;
258
- long converted_ = 0;
983
+ int converted_ = 0;
259
984
  };
260
985
 
261
986
  template<>
262
- class From_Ruby<long*>
987
+ class From_Ruby<int*>
263
988
  {
264
989
  public:
265
- bool is_convertible(VALUE value)
990
+ From_Ruby() = default;
991
+
992
+ explicit From_Ruby(Arg* arg) : arg_(arg)
266
993
  {
267
- return rb_type(value) == RUBY_T_FIXNUM;
268
994
  }
269
995
 
270
- long* convert(VALUE value)
996
+ Convertible is_convertible(VALUE value)
271
997
  {
272
- if (value == Qnil)
273
- {
274
- return nullptr;
275
- }
276
- else
277
- {
278
- this->converted_ = protect(rb_num2long_inline, value);
279
- return &this->converted_;
280
- }
998
+ return FromRubyFundamental<int*>::is_convertible(value);
999
+ }
1000
+
1001
+ int* convert(VALUE value)
1002
+ {
1003
+ return FromRubyFundamental<int*>::convert(value, this->arg_);
281
1004
  }
282
1005
 
283
1006
  private:
284
- long converted_ = 0;
1007
+ Arg* arg_ = nullptr;
285
1008
  };
286
1009
 
287
- // =========== long long ============
288
1010
  template<>
289
- class From_Ruby<long long>
1011
+ class From_Ruby<int**>
290
1012
  {
291
1013
  public:
292
1014
  From_Ruby() = default;
293
1015
 
294
1016
  explicit From_Ruby(Arg* arg) : arg_(arg)
295
1017
  {
1018
+ if (this->arg_ && this->arg_->isOwner())
1019
+ {
1020
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
1021
+ }
296
1022
  }
297
1023
 
298
- bool is_convertible(VALUE value)
1024
+ Convertible is_convertible(VALUE value)
299
1025
  {
300
- return rb_type(value) == RUBY_T_FIXNUM;
1026
+ return FromRubyFundamental<int**>::is_convertible(value);
301
1027
  }
302
1028
 
303
- long long convert(VALUE value)
1029
+ int** convert(VALUE value)
304
1030
  {
305
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
306
- {
307
- return this->arg_->defaultValue<long long>();
308
- }
309
- else
310
- {
311
- return protect(rb_num2ll_inline, value);
312
- }
1031
+ return FromRubyFundamental<int**>::convert(value, this->arg_);
313
1032
  }
314
-
1033
+
315
1034
  private:
316
1035
  Arg* arg_ = nullptr;
317
1036
  };
318
1037
 
1038
+ // =========== unsigned int ============
319
1039
  template<>
320
- class From_Ruby<long long&>
1040
+ class From_Ruby<unsigned int>
321
1041
  {
322
1042
  public:
323
1043
  From_Ruby() = default;
@@ -326,58 +1046,65 @@ namespace Rice::detail
326
1046
  {
327
1047
  }
328
1048
 
329
- bool is_convertible(VALUE value)
1049
+ Convertible is_convertible(VALUE value)
330
1050
  {
331
- return rb_type(value) == RUBY_T_FIXNUM;
1051
+ return FromRubyFundamental<unsigned int>::is_convertible(value);
332
1052
  }
333
1053
 
334
- long long& convert(VALUE value)
1054
+ unsigned int convert(VALUE value)
335
1055
  {
336
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
337
- {
338
- return this->arg_->defaultValue<long long>();
339
- }
340
- else
341
- {
342
- this->converted_ = protect(rb_num2ll_inline, value);
343
- return this->converted_;
344
- }
1056
+ return FromRubyFundamental<unsigned int>::convert(value);
345
1057
  }
346
1058
 
347
1059
  private:
348
1060
  Arg* arg_ = nullptr;
349
- long long converted_ = 0;
350
1061
  };
351
1062
 
352
1063
  template<>
353
- class From_Ruby<long long*>
1064
+ class From_Ruby<unsigned int&>
354
1065
  {
355
1066
  public:
356
- bool is_convertible(VALUE value)
1067
+ using Buffer_T = Buffer<unsigned int>;
1068
+
1069
+ From_Ruby() = default;
1070
+
1071
+ explicit From_Ruby(Arg* arg) : arg_(arg)
357
1072
  {
358
- return rb_type(value) == RUBY_T_FIXNUM;
359
1073
  }
360
1074
 
361
- long long* convert(VALUE value)
1075
+ Convertible is_convertible(VALUE value)
362
1076
  {
363
- if (value == Qnil)
1077
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
364
1078
  {
365
- return nullptr;
1079
+ return Convertible::Exact;
1080
+ }
1081
+ else
1082
+ {
1083
+ return FromRubyFundamental<unsigned int>::is_convertible(value);
1084
+ }
1085
+ }
1086
+
1087
+ unsigned int& convert(VALUE value)
1088
+ {
1089
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1090
+ {
1091
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
1092
+ return buffer->reference();
366
1093
  }
367
1094
  else
368
1095
  {
369
- this->converted_ = protect(rb_num2ll_inline, value);
370
- return &this->converted_;
1096
+ this->converted_ = FromRubyFundamental<unsigned int>::convert(value);
1097
+ return this->converted_;
371
1098
  }
372
1099
  }
373
1100
 
374
1101
  private:
375
- long long converted_ = 0;
1102
+ Arg* arg_ = nullptr;
1103
+ unsigned int converted_ = 0;
376
1104
  };
377
1105
 
378
- // =========== unsigned short ============
379
1106
  template<>
380
- class From_Ruby<unsigned short>
1107
+ class From_Ruby<unsigned int*>
381
1108
  {
382
1109
  public:
383
1110
  From_Ruby() = default;
@@ -386,120 +1113,118 @@ namespace Rice::detail
386
1113
  {
387
1114
  }
388
1115
 
389
- bool is_convertible(VALUE value)
1116
+ Convertible is_convertible(VALUE value)
390
1117
  {
391
- return rb_type(value) == RUBY_T_FIXNUM;
1118
+ return FromRubyFundamental<unsigned int*>::is_convertible(value);
392
1119
  }
393
1120
 
394
- unsigned short convert(VALUE value)
1121
+ unsigned int* convert(VALUE value)
395
1122
  {
396
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
397
- {
398
- return this->arg_->defaultValue<unsigned short>();
399
- }
400
- else
401
- {
402
- return protect(rb_num2ushort, value);
403
- }
1123
+ return FromRubyFundamental<unsigned int*>::convert(value, this->arg_);
404
1124
  }
405
-
1125
+
406
1126
  private:
407
1127
  Arg* arg_ = nullptr;
408
1128
  };
409
1129
 
410
1130
  template<>
411
- class From_Ruby<unsigned short&>
1131
+ class From_Ruby<unsigned int**>
412
1132
  {
413
1133
  public:
414
1134
  From_Ruby() = default;
415
1135
 
416
1136
  explicit From_Ruby(Arg* arg) : arg_(arg)
417
1137
  {
1138
+ if (this->arg_ && this->arg_->isOwner())
1139
+ {
1140
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
1141
+ }
418
1142
  }
419
1143
 
420
- bool is_convertible(VALUE value)
1144
+ Convertible is_convertible(VALUE value)
421
1145
  {
422
- return rb_type(value) == RUBY_T_FIXNUM;
1146
+ return FromRubyFundamental<unsigned int**>::is_convertible(value);
423
1147
  }
424
1148
 
425
- unsigned short& convert(VALUE value)
1149
+ unsigned int** convert(VALUE value)
426
1150
  {
427
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
428
- {
429
- return this->arg_->defaultValue<unsigned short>();
430
- }
431
- else
432
- {
433
- this->converted_ = protect(rb_num2ushort, value);
434
- return this->converted_;
435
- }
1151
+ return FromRubyFundamental<unsigned int**>::convert(value, this->arg_);
436
1152
  }
437
1153
 
438
1154
  private:
439
1155
  Arg* arg_ = nullptr;
440
- unsigned short converted_ = 0;
441
1156
  };
442
1157
 
1158
+ // =========== long ============
443
1159
  template<>
444
- class From_Ruby<unsigned short*>
1160
+ class From_Ruby<long>
445
1161
  {
446
1162
  public:
447
- bool is_convertible(VALUE value)
1163
+ From_Ruby() = default;
1164
+
1165
+ explicit From_Ruby(Arg* arg) : arg_(arg)
448
1166
  {
449
- return rb_type(value) == RUBY_T_FIXNUM;
450
1167
  }
451
1168
 
452
- unsigned short* convert(VALUE value)
1169
+ Convertible is_convertible(VALUE value)
453
1170
  {
454
- if (value == Qnil)
455
- {
456
- return nullptr;
457
- }
458
- else
459
- {
460
- this->converted_ = protect(rb_num2ushort, value);
461
- return &this->converted_;
462
- }
1171
+ return FromRubyFundamental<long>::is_convertible(value);
463
1172
  }
464
1173
 
1174
+ long convert(VALUE value)
1175
+ {
1176
+ return FromRubyFundamental<long>::convert(value);
1177
+ }
1178
+
465
1179
  private:
466
- unsigned short converted_ = 0;
1180
+ Arg* arg_ = nullptr;
467
1181
  };
468
1182
 
469
- // =========== unsigned int ============
470
1183
  template<>
471
- class From_Ruby<unsigned int>
1184
+ class From_Ruby<long&>
472
1185
  {
473
1186
  public:
1187
+ using Buffer_T = Buffer<long>;
1188
+
474
1189
  From_Ruby() = default;
475
1190
 
476
1191
  explicit From_Ruby(Arg* arg) : arg_(arg)
477
1192
  {
478
1193
  }
479
1194
 
480
- bool is_convertible(VALUE value)
1195
+ Convertible is_convertible(VALUE value)
481
1196
  {
482
- return rb_type(value) == RUBY_T_FIXNUM;
1197
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1198
+ {
1199
+ return Convertible::Exact;
1200
+ }
1201
+ else
1202
+ {
1203
+ return FromRubyFundamental<long>::is_convertible(value);
1204
+ }
483
1205
  }
484
1206
 
485
- unsigned int convert(VALUE value)
1207
+ long& convert(VALUE value)
486
1208
  {
487
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1209
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
488
1210
  {
489
- return this->arg_->defaultValue<unsigned int>();
1211
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
1212
+ return buffer->reference();
490
1213
  }
491
1214
  else
492
1215
  {
493
- return (unsigned int)protect(rb_num2ulong_inline, value);
1216
+ this->converted_ = FromRubyFundamental<long>::convert(value);
1217
+ return this->converted_;
494
1218
  }
495
1219
  }
496
-
1220
+
497
1221
  private:
498
1222
  Arg* arg_ = nullptr;
1223
+ long converted_ = 0;
499
1224
  };
500
1225
 
501
1226
  template<>
502
- class From_Ruby<unsigned int&>
1227
+ class From_Ruby<long*>
503
1228
  {
504
1229
  public:
505
1230
  From_Ruby() = default;
@@ -508,53 +1233,46 @@ namespace Rice::detail
508
1233
  {
509
1234
  }
510
1235
 
511
- bool is_convertible(VALUE value)
1236
+ Convertible is_convertible(VALUE value)
512
1237
  {
513
- return rb_type(value) == RUBY_T_FIXNUM;
1238
+ return FromRubyFundamental<long*>::is_convertible(value);
514
1239
  }
515
1240
 
516
- unsigned int& convert(VALUE value)
1241
+ long* convert(VALUE value)
517
1242
  {
518
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
519
- {
520
- return this->arg_->defaultValue<unsigned int>();
521
- }
522
- else
523
- {
524
- this->converted_ = (unsigned int)protect(rb_num2ulong_inline, value);
525
- return this->converted_;
526
- }
1243
+ return FromRubyFundamental<long*>::convert(value, this->arg_);
527
1244
  }
528
1245
 
529
1246
  private:
530
1247
  Arg* arg_ = nullptr;
531
- unsigned int converted_ = 0;
532
1248
  };
533
1249
 
534
1250
  template<>
535
- class From_Ruby<unsigned int*>
1251
+ class From_Ruby<long**>
536
1252
  {
537
1253
  public:
538
- bool is_convertible(VALUE value)
539
- {
540
- return rb_type(value) == RUBY_T_FIXNUM;
541
- }
1254
+ From_Ruby() = default;
542
1255
 
543
- unsigned int* convert(VALUE value)
1256
+ explicit From_Ruby(Arg* arg) : arg_(arg)
544
1257
  {
545
- if (value == Qnil)
546
- {
547
- return nullptr;
548
- }
549
- else
1258
+ if (this->arg_ && this->arg_->isOwner())
550
1259
  {
551
- this->converted_ = (unsigned int)protect(rb_num2ulong_inline, value);
552
- return &this->converted_;
1260
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
553
1261
  }
554
1262
  }
555
1263
 
1264
+ Convertible is_convertible(VALUE value)
1265
+ {
1266
+ return FromRubyFundamental<long**>::is_convertible(value);
1267
+ }
1268
+
1269
+ long** convert(VALUE value)
1270
+ {
1271
+ return FromRubyFundamental<long**>::convert(value, this->arg_);
1272
+ }
1273
+
556
1274
  private:
557
- unsigned int converted_ = 0;
1275
+ Arg* arg_ = nullptr;
558
1276
  };
559
1277
 
560
1278
  // =========== unsigned long ============
@@ -568,9 +1286,9 @@ namespace Rice::detail
568
1286
  {
569
1287
  }
570
1288
 
571
- bool is_convertible(VALUE value)
1289
+ Convertible is_convertible(VALUE value)
572
1290
  {
573
- return rb_type(value) == RUBY_T_FIXNUM;
1291
+ return FromRubyFundamental<unsigned long>::is_convertible(value);
574
1292
  }
575
1293
 
576
1294
  unsigned long convert(VALUE value)
@@ -579,16 +1297,12 @@ namespace Rice::detail
579
1297
  {
580
1298
  return (unsigned long)value;
581
1299
  }
582
- else if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
583
- {
584
- return this->arg_->defaultValue<unsigned long>();
585
- }
586
1300
  else
587
1301
  {
588
- return protect(rb_num2ulong_inline, value);
1302
+ return FromRubyFundamental<unsigned long>::convert(value);
589
1303
  }
590
1304
  }
591
-
1305
+
592
1306
  private:
593
1307
  Arg* arg_ = nullptr;
594
1308
  };
@@ -597,26 +1311,36 @@ namespace Rice::detail
597
1311
  class From_Ruby<unsigned long&>
598
1312
  {
599
1313
  public:
1314
+ using Buffer_T = Buffer<unsigned long>;
1315
+
600
1316
  From_Ruby() = default;
601
1317
 
602
1318
  explicit From_Ruby(Arg* arg) : arg_(arg)
603
1319
  {
604
1320
  }
605
1321
 
606
- bool is_convertible(VALUE value)
1322
+ Convertible is_convertible(VALUE value)
607
1323
  {
608
- return rb_type(value) == RUBY_T_FIXNUM;
1324
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1325
+ {
1326
+ return Convertible::Exact;
1327
+ }
1328
+ else
1329
+ {
1330
+ return FromRubyFundamental<unsigned long>::is_convertible(value);
1331
+ }
609
1332
  }
610
1333
 
611
1334
  unsigned long& convert(VALUE value)
612
1335
  {
613
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1336
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
614
1337
  {
615
- return this->arg_->defaultValue<unsigned long>();
1338
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
1339
+ return buffer->reference();
616
1340
  }
617
1341
  else
618
1342
  {
619
- this->converted_ = protect(rb_num2ulong_inline, value);
1343
+ this->converted_ = FromRubyFundamental<unsigned long>::convert(value);
620
1344
  return this->converted_;
621
1345
  }
622
1346
  }
@@ -630,26 +1354,52 @@ namespace Rice::detail
630
1354
  class From_Ruby<unsigned long*>
631
1355
  {
632
1356
  public:
633
- bool is_convertible(VALUE value)
1357
+ From_Ruby() = default;
1358
+
1359
+ explicit From_Ruby(Arg* arg) : arg_(arg)
1360
+ {
1361
+ }
1362
+
1363
+ Convertible is_convertible(VALUE value)
634
1364
  {
635
- return rb_type(value) == RUBY_T_FIXNUM;
1365
+ return FromRubyFundamental<unsigned long*>::is_convertible(value);
636
1366
  }
637
1367
 
638
1368
  unsigned long* convert(VALUE value)
639
1369
  {
640
- if (value == Qnil)
641
- {
642
- return nullptr;
643
- }
644
- else
1370
+ return FromRubyFundamental<unsigned long*>::convert(value, this->arg_);
1371
+ }
1372
+
1373
+ private:
1374
+ Arg* arg_ = nullptr;
1375
+ };
1376
+
1377
+ template<>
1378
+ class From_Ruby<unsigned long**>
1379
+ {
1380
+ public:
1381
+ From_Ruby() = default;
1382
+
1383
+ explicit From_Ruby(Arg* arg) : arg_(arg)
1384
+ {
1385
+ if (this->arg_ && this->arg_->isOwner())
645
1386
  {
646
- this->converted_ = protect(rb_num2ulong_inline, value);
647
- return &this->converted_;
1387
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
648
1388
  }
649
1389
  }
650
1390
 
1391
+ Convertible is_convertible(VALUE value)
1392
+ {
1393
+ return FromRubyFundamental<unsigned long**>::is_convertible(value);
1394
+ }
1395
+
1396
+ unsigned long** convert(VALUE value)
1397
+ {
1398
+ return FromRubyFundamental<unsigned long**>::convert(value, this->arg_);
1399
+ }
1400
+
651
1401
  private:
652
- unsigned long converted_ = 0;
1402
+ Arg* arg_ = nullptr;
653
1403
  };
654
1404
 
655
1405
  // =========== unsigned long long ============
@@ -663,9 +1413,9 @@ namespace Rice::detail
663
1413
  {
664
1414
  }
665
1415
 
666
- bool is_convertible(VALUE value)
1416
+ Convertible is_convertible(VALUE value)
667
1417
  {
668
- return rb_type(value) == RUBY_T_FIXNUM;
1418
+ return FromRubyFundamental<unsigned long long>::is_convertible(value);
669
1419
  }
670
1420
 
671
1421
  unsigned long long convert(VALUE value)
@@ -674,16 +1424,12 @@ namespace Rice::detail
674
1424
  {
675
1425
  return value;
676
1426
  }
677
- else if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
678
- {
679
- return this->arg_->defaultValue<unsigned long long>();
680
- }
681
1427
  else
682
1428
  {
683
- return protect(rb_num2ull, value);
1429
+ return FromRubyFundamental<unsigned long long>::convert(value);
684
1430
  }
685
1431
  }
686
-
1432
+
687
1433
  private:
688
1434
  Arg* arg_ = nullptr;
689
1435
  };
@@ -692,26 +1438,36 @@ namespace Rice::detail
692
1438
  class From_Ruby<unsigned long long&>
693
1439
  {
694
1440
  public:
1441
+ using Buffer_T = Buffer<unsigned long long>;
1442
+
695
1443
  From_Ruby() = default;
696
1444
 
697
1445
  explicit From_Ruby(Arg* arg) : arg_(arg)
698
1446
  {
699
1447
  }
700
1448
 
701
- bool is_convertible(VALUE value)
1449
+ Convertible is_convertible(VALUE value)
702
1450
  {
703
- return rb_type(value) == RUBY_T_FIXNUM;
1451
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1452
+ {
1453
+ return Convertible::Exact;
1454
+ }
1455
+ else
1456
+ {
1457
+ return FromRubyFundamental<unsigned long long>::is_convertible(value);
1458
+ }
704
1459
  }
705
1460
 
706
1461
  unsigned long long& convert(VALUE value)
707
1462
  {
708
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1463
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
709
1464
  {
710
- return this->arg_->defaultValue<unsigned long long>();
1465
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
1466
+ return buffer->reference();
711
1467
  }
712
1468
  else
713
1469
  {
714
- this->converted_ = protect(rb_num2ull, value);
1470
+ this->converted_ = FromRubyFundamental<unsigned long long>::convert(value);
715
1471
  return this->converted_;
716
1472
  }
717
1473
  }
@@ -725,31 +1481,57 @@ namespace Rice::detail
725
1481
  class From_Ruby<unsigned long long*>
726
1482
  {
727
1483
  public:
728
- bool is_convertible(VALUE value)
1484
+ From_Ruby() = default;
1485
+
1486
+ explicit From_Ruby(Arg* arg) : arg_(arg)
729
1487
  {
730
- return rb_type(value) == RUBY_T_FIXNUM;
1488
+ }
1489
+
1490
+ Convertible is_convertible(VALUE value)
1491
+ {
1492
+ return FromRubyFundamental<unsigned long long*>::is_convertible(value);
731
1493
  }
732
1494
 
733
1495
  unsigned long long* convert(VALUE value)
734
1496
  {
735
- if (value == Qnil)
736
- {
737
- return nullptr;
738
- }
739
- else
1497
+ return FromRubyFundamental<unsigned long long*>::convert(value, this->arg_);
1498
+ }
1499
+
1500
+ private:
1501
+ Arg* arg_ = nullptr;
1502
+ };
1503
+
1504
+ template<>
1505
+ class From_Ruby<unsigned long long**>
1506
+ {
1507
+ public:
1508
+ From_Ruby() = default;
1509
+
1510
+ explicit From_Ruby(Arg* arg) : arg_(arg)
1511
+ {
1512
+ if (this->arg_ && this->arg_->isOwner())
740
1513
  {
741
- this->converted_ = protect(rb_num2ull, value);
742
- return &this->converted_;
1514
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
743
1515
  }
744
1516
  }
745
1517
 
1518
+ Convertible is_convertible(VALUE value)
1519
+ {
1520
+ return FromRubyFundamental<unsigned long long**>::is_convertible(value);
1521
+ }
1522
+
1523
+ unsigned long long** convert(VALUE value)
1524
+ {
1525
+ return FromRubyFundamental<unsigned long long**>::convert(value, this->arg_);
1526
+ }
1527
+
746
1528
  private:
747
- unsigned long long converted_ = 0;
1529
+ Arg* arg_ = nullptr;
748
1530
  };
749
-
750
- // =========== bool ============
1531
+
1532
+ // =========== long long ============
751
1533
  template<>
752
- class From_Ruby<bool>
1534
+ class From_Ruby<long long>
753
1535
  {
754
1536
  public:
755
1537
  From_Ruby() = default;
@@ -758,24 +1540,14 @@ namespace Rice::detail
758
1540
  {
759
1541
  }
760
1542
 
761
- bool is_convertible(VALUE value)
1543
+ Convertible is_convertible(VALUE value)
762
1544
  {
763
- ruby_value_type ruby_type = (ruby_value_type)rb_type(value);
764
- return ruby_type == RUBY_T_TRUE ||
765
- ruby_type == RUBY_T_FALSE ||
766
- ruby_type == RUBY_T_NIL;
1545
+ return FromRubyFundamental<long long>::is_convertible(value);
767
1546
  }
768
1547
 
769
- bool convert(VALUE value)
1548
+ long long convert(VALUE value)
770
1549
  {
771
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
772
- {
773
- return this->arg_->defaultValue<bool>();
774
- }
775
- else
776
- {
777
- return RTEST(value);
778
- }
1550
+ return FromRubyFundamental<long long>::convert(value);
779
1551
  }
780
1552
 
781
1553
  private:
@@ -783,134 +1555,103 @@ namespace Rice::detail
783
1555
  };
784
1556
 
785
1557
  template<>
786
- class From_Ruby<bool&>
1558
+ class From_Ruby<long long&>
787
1559
  {
788
1560
  public:
1561
+ using Buffer_T = Buffer<long long>;
1562
+
789
1563
  From_Ruby() = default;
790
1564
 
791
1565
  explicit From_Ruby(Arg* arg) : arg_(arg)
792
1566
  {
793
1567
  }
794
1568
 
795
- bool is_convertible(VALUE value)
1569
+ Convertible is_convertible(VALUE value)
796
1570
  {
797
- ruby_value_type ruby_type = (ruby_value_type)rb_type(value);
798
- return ruby_type == RUBY_T_TRUE ||
799
- ruby_type == RUBY_T_FALSE ||
800
- ruby_type == RUBY_T_NIL;
1571
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1572
+ {
1573
+ return Convertible::Exact;
1574
+ }
1575
+ else
1576
+ {
1577
+ return FromRubyFundamental<long long>::is_convertible(value);
1578
+ }
801
1579
  }
802
1580
 
803
- bool& convert(VALUE value)
1581
+ long long& convert(VALUE value)
804
1582
  {
805
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1583
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
806
1584
  {
807
- return this->arg_->defaultValue<bool>();
1585
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
1586
+ return buffer->reference();
808
1587
  }
809
1588
  else
810
1589
  {
811
- this->converted_ = RTEST(value);
1590
+ this->converted_ = FromRubyFundamental<long long>::convert(value);
812
1591
  return this->converted_;
813
1592
  }
814
1593
  }
815
1594
 
816
1595
  private:
817
1596
  Arg* arg_ = nullptr;
818
- bool converted_ = false;
1597
+ long long converted_ = 0;
819
1598
  };
820
1599
 
821
1600
  template<>
822
- class From_Ruby<bool*>
1601
+ class From_Ruby<long long*>
823
1602
  {
824
1603
  public:
825
- bool is_convertible(VALUE value)
1604
+ From_Ruby() = default;
1605
+
1606
+ explicit From_Ruby(Arg* arg) : arg_(arg)
826
1607
  {
827
- ruby_value_type ruby_type = (ruby_value_type)rb_type(value);
828
- return ruby_type == RUBY_T_TRUE ||
829
- ruby_type == RUBY_T_FALSE ||
830
- ruby_type == RUBY_T_NIL;
831
1608
  }
832
1609
 
833
- bool* convert(VALUE value)
1610
+ Convertible is_convertible(VALUE value)
834
1611
  {
835
- if (value == Qnil)
836
- {
837
- return nullptr;
838
- }
839
- else
840
- {
841
- this->converted_ = RTEST(value);
842
- return &this->converted_;
843
- }
1612
+ return FromRubyFundamental<long long*>::is_convertible(value);
1613
+ }
1614
+
1615
+ long long* convert(VALUE value)
1616
+ {
1617
+ return FromRubyFundamental<long long*>::convert(value, this->arg_);
844
1618
  }
845
1619
 
846
1620
  private:
847
- bool converted_ = false;
1621
+ Arg* arg_ = nullptr;
848
1622
  };
849
1623
 
850
- // =========== char ============
851
- template<typename T>
852
- inline T charFromRuby(VALUE value)
853
- {
854
- switch (rb_type(value))
855
- {
856
- case T_STRING:
857
- {
858
- if (RSTRING_LEN(value) == 1)
859
- {
860
- return RSTRING_PTR(value)[0];
861
- }
862
- else
863
- {
864
- throw std::invalid_argument("from_ruby<char>: string must have length 1");
865
- }
866
- break;
867
- }
868
- case T_FIXNUM:
869
- {
870
- return From_Ruby<long>().convert(value) & 0xff;
871
- break;
872
- }
873
- default:
874
- {
875
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
876
- detail::protect(rb_obj_classname, value), "char type");
877
- }
878
- }
879
- }
880
-
881
1624
  template<>
882
- class From_Ruby<char>
1625
+ class From_Ruby<long long**>
883
1626
  {
884
1627
  public:
885
1628
  From_Ruby() = default;
886
1629
 
887
1630
  explicit From_Ruby(Arg* arg) : arg_(arg)
888
1631
  {
1632
+ if (this->arg_ && this->arg_->isOwner())
1633
+ {
1634
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
1635
+ }
889
1636
  }
890
1637
 
891
- bool is_convertible(VALUE value)
1638
+ Convertible is_convertible(VALUE value)
892
1639
  {
893
- return rb_type(value) == RUBY_T_STRING;
1640
+ return FromRubyFundamental<long long**>::is_convertible(value);
894
1641
  }
895
1642
 
896
- char convert(VALUE value)
1643
+ long long** convert(VALUE value)
897
1644
  {
898
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
899
- {
900
- return this->arg_->defaultValue<char>();
901
- }
902
- else
903
- {
904
- return charFromRuby<char>(value);
905
- }
1645
+ return FromRubyFundamental<long long**>::convert(value, this->arg_);
906
1646
  }
907
-
1647
+
908
1648
  private:
909
1649
  Arg* arg_ = nullptr;
910
1650
  };
911
1651
 
1652
+ // =========== short ============
912
1653
  template<>
913
- class From_Ruby<char&>
1654
+ class From_Ruby<short>
914
1655
  {
915
1656
  public:
916
1657
  From_Ruby() = default;
@@ -919,79 +1660,65 @@ namespace Rice::detail
919
1660
  {
920
1661
  }
921
1662
 
922
- bool is_convertible(VALUE value)
1663
+ Convertible is_convertible(VALUE value)
923
1664
  {
924
- return rb_type(value) == RUBY_T_STRING;
1665
+ return FromRubyFundamental<short>::is_convertible(value);
925
1666
  }
926
1667
 
927
- char& convert(VALUE value)
1668
+ short convert(VALUE value)
928
1669
  {
929
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
930
- {
931
- return this->arg_->defaultValue<char>();
932
- }
933
- else
934
- {
935
- this->converted_ = charFromRuby<char>(value);
936
- return this->converted_;
937
- }
1670
+ return FromRubyFundamental<short>::convert(value);
938
1671
  }
939
1672
 
940
1673
  private:
941
1674
  Arg* arg_ = nullptr;
942
- char converted_ = 0;
943
1675
  };
944
1676
 
945
1677
  template<>
946
- class From_Ruby<char*>
1678
+ class From_Ruby<short&>
947
1679
  {
948
1680
  public:
949
- bool is_convertible(VALUE value)
1681
+ using Buffer_T = Buffer<short>;
1682
+
1683
+ From_Ruby() = default;
1684
+
1685
+ explicit From_Ruby(Arg* arg) : arg_(arg)
950
1686
  {
951
- return rb_type(value) == RUBY_T_STRING;
952
1687
  }
953
1688
 
954
- char* convert(VALUE value)
1689
+ Convertible is_convertible(VALUE value)
955
1690
  {
956
- if (value == Qnil)
1691
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
957
1692
  {
958
- return nullptr;
1693
+ return Convertible::Exact;
959
1694
  }
960
1695
  else
961
1696
  {
962
- detail::protect(rb_check_type, value, (int)T_STRING);
963
- return RSTRING_PTR(value);
1697
+ return FromRubyFundamental<short>::is_convertible(value);
964
1698
  }
965
1699
  }
966
- };
967
-
968
- // This is mostly for testing. NativeFunction removes const before calling From_Ruby
969
- template<>
970
- class From_Ruby<char const*>
971
- {
972
- public:
973
- bool is_convertible(VALUE value)
974
- {
975
- return rb_type(value) == RUBY_T_STRING;
976
- }
977
1700
 
978
- char const* convert(VALUE value)
1701
+ short& convert(VALUE value)
979
1702
  {
980
- if (value == Qnil)
1703
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
981
1704
  {
982
- return nullptr;
1705
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
1706
+ return buffer->reference();
983
1707
  }
984
1708
  else
985
1709
  {
986
- detail::protect(rb_check_type, value, (int)T_STRING);
987
- return RSTRING_PTR(value);
1710
+ this->converted_ = FromRubyFundamental<short>::convert(value);
1711
+ return this->converted_;
988
1712
  }
989
1713
  }
1714
+
1715
+ private:
1716
+ Arg* arg_ = nullptr;
1717
+ short converted_ = 0;
990
1718
  };
991
1719
 
992
- // =========== unsinged char ============
993
1720
  template<>
994
- class From_Ruby<unsigned char>
1721
+ class From_Ruby<short*>
995
1722
  {
996
1723
  public:
997
1724
  From_Ruby() = default;
@@ -1000,62 +1727,50 @@ namespace Rice::detail
1000
1727
  {
1001
1728
  }
1002
1729
 
1003
- bool is_convertible(VALUE value)
1730
+ Convertible is_convertible(VALUE value)
1004
1731
  {
1005
- return rb_type(value) == RUBY_T_STRING;
1732
+ return FromRubyFundamental<short*>::is_convertible(value);
1006
1733
  }
1007
1734
 
1008
- unsigned char convert(VALUE value)
1735
+ short* convert(VALUE value)
1009
1736
  {
1010
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1011
- {
1012
- return this->arg_->defaultValue<unsigned char>();
1013
- }
1014
- else
1015
- {
1016
- return charFromRuby<unsigned char>(value);
1017
- }
1737
+ return FromRubyFundamental<short*>::convert(value, this->arg_);
1018
1738
  }
1019
-
1739
+
1020
1740
  private:
1021
1741
  Arg* arg_ = nullptr;
1022
1742
  };
1023
1743
 
1024
- // =========== signed char ============
1025
1744
  template<>
1026
- class From_Ruby<signed char>
1745
+ class From_Ruby<short**>
1027
1746
  {
1028
1747
  public:
1029
1748
  From_Ruby() = default;
1030
1749
 
1031
1750
  explicit From_Ruby(Arg* arg) : arg_(arg)
1032
1751
  {
1752
+ if (this->arg_ && this->arg_->isOwner())
1753
+ {
1754
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
1755
+ }
1033
1756
  }
1034
1757
 
1035
- bool is_convertible(VALUE value)
1758
+ Convertible is_convertible(VALUE value)
1036
1759
  {
1037
- return rb_type(value) == RUBY_T_STRING;
1760
+ return FromRubyFundamental<short**>::is_convertible(value);
1038
1761
  }
1039
1762
 
1040
- signed char convert(VALUE value)
1763
+ short** convert(VALUE value)
1041
1764
  {
1042
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1043
- {
1044
- return this->arg_->defaultValue<signed char>();
1045
- }
1046
- else
1047
- {
1048
- return charFromRuby<signed char>(value);
1049
- }
1765
+ return FromRubyFundamental<short**>::convert(value, this->arg_);
1050
1766
  }
1051
-
1052
1767
  private:
1053
1768
  Arg* arg_ = nullptr;
1054
1769
  };
1055
1770
 
1056
- // =========== double ============
1771
+ // =========== unsigned short ============
1057
1772
  template<>
1058
- class From_Ruby<double>
1773
+ class From_Ruby<unsigned short>
1059
1774
  {
1060
1775
  public:
1061
1776
  From_Ruby() = default;
@@ -1064,21 +1779,14 @@ namespace Rice::detail
1064
1779
  {
1065
1780
  }
1066
1781
 
1067
- bool is_convertible(VALUE value)
1782
+ Convertible is_convertible(VALUE value)
1068
1783
  {
1069
- return rb_type(value) == RUBY_T_FLOAT;
1784
+ return FromRubyFundamental<unsigned short>::is_convertible(value);
1070
1785
  }
1071
1786
 
1072
- double convert(VALUE value)
1787
+ unsigned short convert(VALUE value)
1073
1788
  {
1074
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1075
- {
1076
- return this->arg_->defaultValue<double>();
1077
- }
1078
- else
1079
- {
1080
- return protect(rb_num2dbl, value);
1081
- }
1789
+ return FromRubyFundamental<unsigned short>::convert(value);
1082
1790
  }
1083
1791
 
1084
1792
  private:
@@ -1086,153 +1794,274 @@ namespace Rice::detail
1086
1794
  };
1087
1795
 
1088
1796
  template<>
1089
- class From_Ruby<double&>
1797
+ class From_Ruby<unsigned short&>
1090
1798
  {
1091
1799
  public:
1800
+ using Buffer_T = Buffer<unsigned short>;
1801
+
1092
1802
  From_Ruby() = default;
1093
1803
 
1094
1804
  explicit From_Ruby(Arg* arg) : arg_(arg)
1095
1805
  {
1096
1806
  }
1097
1807
 
1098
- bool is_convertible(VALUE value)
1808
+ Convertible is_convertible(VALUE value)
1099
1809
  {
1100
- return rb_type(value) == RUBY_T_FLOAT;
1810
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1811
+ {
1812
+ return Convertible::Exact;
1813
+ }
1814
+ else
1815
+ {
1816
+ return FromRubyFundamental<unsigned short>::is_convertible(value);
1817
+ }
1101
1818
  }
1102
1819
 
1103
- double& convert(VALUE value)
1820
+ unsigned short& convert(VALUE value)
1104
1821
  {
1105
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1822
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1106
1823
  {
1107
- return this->arg_->defaultValue<double>();
1824
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
1825
+ return buffer->reference();
1108
1826
  }
1109
1827
  else
1110
1828
  {
1111
- this->converted_ = protect(rb_num2dbl, value);
1829
+ this->converted_ = FromRubyFundamental<unsigned short>::convert(value);
1112
1830
  return this->converted_;
1113
1831
  }
1114
1832
  }
1115
1833
 
1116
1834
  private:
1117
1835
  Arg* arg_ = nullptr;
1118
- double converted_;
1836
+ unsigned short converted_ = 0;
1119
1837
  };
1120
1838
 
1121
1839
  template<>
1122
- class From_Ruby<double*>
1840
+ class From_Ruby<unsigned short*>
1123
1841
  {
1124
1842
  public:
1125
- bool is_convertible(VALUE value)
1843
+ From_Ruby() = default;
1844
+
1845
+ explicit From_Ruby(Arg* arg) : arg_(arg)
1126
1846
  {
1127
- return rb_type(value) == RUBY_T_FLOAT;
1128
1847
  }
1129
1848
 
1130
- double* convert(VALUE value)
1849
+ Convertible is_convertible(VALUE value)
1131
1850
  {
1132
- if (value == Qnil)
1133
- {
1134
- return nullptr;
1135
- }
1136
- else
1137
- {
1138
- this->converted_ = protect(rb_num2dbl, value);
1139
- return &this->converted_;
1140
- }
1851
+ return FromRubyFundamental<unsigned short*>::is_convertible(value);
1852
+ }
1853
+
1854
+ unsigned short* convert(VALUE value)
1855
+ {
1856
+ return FromRubyFundamental<unsigned short*>::convert(value, this->arg_);
1141
1857
  }
1142
1858
 
1143
1859
  private:
1144
- double converted_;
1860
+ Arg* arg_ = nullptr;
1145
1861
  };
1146
1862
 
1147
- // =========== float ============
1148
1863
  template<>
1149
- class From_Ruby<float>
1864
+ class From_Ruby<unsigned short**>
1150
1865
  {
1151
1866
  public:
1152
1867
  From_Ruby() = default;
1153
1868
 
1154
1869
  explicit From_Ruby(Arg* arg) : arg_(arg)
1155
1870
  {
1871
+ if (this->arg_ && this->arg_->isOwner())
1872
+ {
1873
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
1874
+ }
1156
1875
  }
1157
1876
 
1158
- bool is_convertible(VALUE value)
1877
+ Convertible is_convertible(VALUE value)
1159
1878
  {
1160
- return rb_type(value) == RUBY_T_FLOAT;
1879
+ return FromRubyFundamental<unsigned short**>::is_convertible(value);
1161
1880
  }
1162
1881
 
1163
- float convert(VALUE value)
1882
+ unsigned short** convert(VALUE value)
1164
1883
  {
1165
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1166
- {
1167
- return this->arg_->defaultValue<float>();
1168
- }
1169
- else
1170
- {
1171
- return (float)protect(rb_num2dbl, value);
1172
- }
1884
+ return FromRubyFundamental<unsigned short**>::convert(value, this->arg_);
1173
1885
  }
1174
-
1886
+
1175
1887
  private:
1176
1888
  Arg* arg_ = nullptr;
1177
1889
  };
1178
1890
 
1891
+ // =========== std::nullptr_t ============
1179
1892
  template<>
1180
- class From_Ruby<float&>
1893
+ class From_Ruby<std::nullptr_t>
1181
1894
  {
1182
1895
  public:
1183
1896
  From_Ruby() = default;
1184
1897
 
1185
1898
  explicit From_Ruby(Arg* arg) : arg_(arg)
1186
1899
  {
1900
+ if (this->arg_->isOwner())
1901
+ {
1902
+ throw Exception(rb_eTypeError, "Cannot transfer ownership of C++ void pointer");
1903
+ }
1187
1904
  }
1188
1905
 
1189
- bool is_convertible(VALUE value)
1906
+ Convertible is_convertible(VALUE value)
1190
1907
  {
1191
- return rb_type(value) == RUBY_T_FLOAT;
1908
+ if (this->arg_ && this->arg_->isOpaque())
1909
+ {
1910
+ return Convertible::Exact;
1911
+ }
1912
+
1913
+ switch (rb_type(value))
1914
+ {
1915
+ case RUBY_T_NIL:
1916
+ {
1917
+ return Convertible::Exact;
1918
+ break;
1919
+ }
1920
+ default:
1921
+ {
1922
+ return Convertible::None;
1923
+ }
1924
+ }
1192
1925
  }
1193
1926
 
1194
- float& convert(VALUE value)
1927
+ void* convert(VALUE value)
1195
1928
  {
1196
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1929
+ if (value == Qnil)
1197
1930
  {
1198
- return this->arg_->defaultValue<float>();
1931
+ return nullptr;
1199
1932
  }
1200
- else
1933
+
1934
+ if (this->arg_ && this->arg_->isOpaque())
1201
1935
  {
1202
- this->converted_ = (float)protect(rb_num2dbl, value);
1203
- return this->converted_;
1936
+ return (void*)value;
1204
1937
  }
1205
- }
1206
1938
 
1939
+ switch (rb_type(value))
1940
+ {
1941
+ case RUBY_T_NIL:
1942
+ {
1943
+ return nullptr;
1944
+ break;
1945
+ }
1946
+ default:
1947
+ {
1948
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
1949
+ detail::protect(rb_obj_classname, value), "nil");
1950
+ }
1951
+ }
1952
+ }
1207
1953
  private:
1208
1954
  Arg* arg_ = nullptr;
1209
- float converted_;
1210
1955
  };
1211
1956
 
1957
+ // =========== void ============
1212
1958
  template<>
1213
- class From_Ruby<float*>
1959
+ class From_Ruby<void*>
1214
1960
  {
1215
1961
  public:
1216
- bool is_convertible(VALUE value)
1962
+ From_Ruby()
1963
+ {
1964
+ detail::Type<Buffer<void>>::verify();
1965
+ };
1966
+
1967
+ explicit From_Ruby(Arg* arg) : arg_(arg)
1217
1968
  {
1218
- return rb_type(value) == RUBY_T_FLOAT;
1969
+ detail::Type<Buffer<void>>::verify();
1970
+
1971
+ if (this->arg_->isOwner())
1972
+ {
1973
+ throw Exception(rb_eTypeError, "Cannot transfer ownership of C++ void pointer");
1974
+ }
1219
1975
  }
1220
1976
 
1221
- float* convert(VALUE value)
1977
+ Convertible is_convertible(VALUE value)
1978
+ {
1979
+ if (this->arg_ && this->arg_->isOpaque())
1980
+ {
1981
+ return Convertible::Exact;
1982
+ }
1983
+
1984
+ switch (rb_type(value))
1985
+ {
1986
+ case RUBY_T_DATA:
1987
+ {
1988
+ return Convertible::Cast;
1989
+ break;
1990
+ }
1991
+ case RUBY_T_STRING:
1992
+ {
1993
+ if (RB_ENCODING_IS_ASCII8BIT(value))
1994
+ return Convertible::Exact;
1995
+ else
1996
+ return Convertible::None;
1997
+ break;
1998
+ }
1999
+ case RUBY_T_NIL:
2000
+ {
2001
+ return Convertible::Exact;
2002
+ break;
2003
+ }
2004
+ default:
2005
+ {
2006
+ return Convertible::None;
2007
+ }
2008
+ }
2009
+ }
2010
+
2011
+ void* convert(VALUE value)
1222
2012
  {
1223
2013
  if (value == Qnil)
1224
2014
  {
1225
2015
  return nullptr;
1226
2016
  }
1227
- else
2017
+
2018
+ if (this->arg_ && this->arg_->isOpaque())
1228
2019
  {
1229
- this->converted_ = (float)protect(rb_num2dbl, value);
1230
- return &this->converted_;
2020
+ return (void*)value;
1231
2021
  }
1232
- }
1233
2022
 
2023
+ switch (rb_type(value))
2024
+ {
2025
+ case RUBY_T_DATA:
2026
+ {
2027
+ // Since C++ is not telling us type information, we need to extract it
2028
+ // from the Ruby object.
2029
+ const rb_data_type_t* rb_type = RTYPEDDATA_TYPE(value);
2030
+
2031
+ // Is this a Buffer? It could also be a pointer to any other object being passed to
2032
+ // a C++ paramter that takes void*
2033
+ if (rb_type == Data_Type<Buffer<void>>::ruby_data_type())
2034
+ {
2035
+ Data_Object<Buffer<void>> buffer(value);
2036
+ return buffer->ptr();
2037
+ }
2038
+ else
2039
+ {
2040
+ return detail::unwrap<void>(value, (rb_data_type_t*)rb_type, this->arg_ && this->arg_->isOwner());
2041
+ }
2042
+
2043
+ break;
2044
+ }
2045
+ case RUBY_T_STRING:
2046
+ {
2047
+ // String must be formatted in a way the receiver understands! This likely means it was created
2048
+ // by Array.pack. Once the underlying string goes away the passed in data becomes invalid!
2049
+ return (void*)RSTRING_PTR(value);
2050
+ break;
2051
+ }
2052
+ case RUBY_T_NIL:
2053
+ {
2054
+ return nullptr;
2055
+ break;
2056
+ }
2057
+ default:
2058
+ {
2059
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
2060
+ detail::protect(rb_obj_classname, value), "pointer");
2061
+ }
2062
+ }
2063
+ }
1234
2064
  private:
1235
- float converted_;
2065
+ Arg* arg_ = nullptr;
1236
2066
  };
1237
- }
1238
- #endif // Rice__detail__from_ruby__ipp_
2067
+ }