rice 4.3.2 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -25
  3. data/README.md +7 -2
  4. data/Rakefile +7 -1
  5. data/include/rice/rice.hpp +7321 -4470
  6. data/include/rice/stl.hpp +769 -222
  7. data/lib/mkmf-rice.rb +37 -95
  8. data/rice/Address_Registration_Guard.hpp +72 -3
  9. data/rice/Arg.hpp +19 -5
  10. data/rice/Arg.ipp +24 -0
  11. data/rice/Callback.hpp +21 -0
  12. data/rice/Callback.ipp +13 -0
  13. data/rice/Constructor.hpp +4 -27
  14. data/rice/Constructor.ipp +79 -0
  15. data/rice/Data_Object.hpp +74 -3
  16. data/rice/Data_Object.ipp +324 -32
  17. data/rice/Data_Type.hpp +215 -3
  18. data/rice/Data_Type.ipp +125 -64
  19. data/rice/Director.hpp +0 -2
  20. data/rice/Enum.hpp +4 -6
  21. data/rice/Enum.ipp +101 -57
  22. data/rice/Exception.hpp +62 -2
  23. data/rice/Exception.ipp +7 -12
  24. data/rice/JumpException.hpp +44 -0
  25. data/rice/JumpException.ipp +48 -0
  26. data/rice/MemoryView.hpp +11 -0
  27. data/rice/MemoryView.ipp +43 -0
  28. data/rice/Return.hpp +6 -26
  29. data/rice/Return.ipp +10 -16
  30. data/rice/detail/DefaultHandler.hpp +12 -0
  31. data/rice/detail/DefaultHandler.ipp +8 -0
  32. data/rice/detail/HandlerRegistry.hpp +5 -35
  33. data/rice/detail/HandlerRegistry.ipp +7 -11
  34. data/rice/detail/InstanceRegistry.hpp +1 -4
  35. data/rice/detail/MethodInfo.hpp +15 -5
  36. data/rice/detail/MethodInfo.ipp +78 -6
  37. data/rice/detail/Native.hpp +32 -0
  38. data/rice/detail/Native.ipp +129 -0
  39. data/rice/detail/NativeAttributeGet.hpp +51 -0
  40. data/rice/detail/NativeAttributeGet.ipp +51 -0
  41. data/rice/detail/NativeAttributeSet.hpp +43 -0
  42. data/rice/detail/NativeAttributeSet.ipp +82 -0
  43. data/rice/detail/NativeCallbackFFI.hpp +55 -0
  44. data/rice/detail/NativeCallbackFFI.ipp +151 -0
  45. data/rice/detail/NativeCallbackSimple.hpp +30 -0
  46. data/rice/detail/NativeCallbackSimple.ipp +29 -0
  47. data/rice/detail/NativeFunction.hpp +20 -21
  48. data/rice/detail/NativeFunction.ipp +199 -64
  49. data/rice/detail/NativeIterator.hpp +8 -11
  50. data/rice/detail/NativeIterator.ipp +27 -31
  51. data/rice/detail/NativeRegistry.hpp +24 -17
  52. data/rice/detail/NativeRegistry.ipp +23 -56
  53. data/rice/detail/Proc.hpp +4 -0
  54. data/rice/detail/Proc.ipp +85 -0
  55. data/rice/detail/Registries.hpp +0 -7
  56. data/rice/detail/Registries.ipp +0 -18
  57. data/rice/detail/RubyFunction.hpp +0 -3
  58. data/rice/detail/RubyFunction.ipp +4 -8
  59. data/rice/detail/RubyType.hpp +19 -0
  60. data/rice/detail/RubyType.ipp +187 -0
  61. data/rice/detail/TupleIterator.hpp +14 -0
  62. data/rice/detail/Type.hpp +5 -6
  63. data/rice/detail/Type.ipp +150 -33
  64. data/rice/detail/TypeRegistry.hpp +15 -7
  65. data/rice/detail/TypeRegistry.ipp +105 -12
  66. data/rice/detail/Wrapper.hpp +6 -5
  67. data/rice/detail/Wrapper.ipp +45 -23
  68. data/rice/detail/cpp_protect.hpp +5 -6
  69. data/rice/detail/default_allocation_func.ipp +0 -2
  70. data/rice/detail/from_ruby.hpp +37 -3
  71. data/rice/detail/from_ruby.ipp +911 -454
  72. data/rice/detail/ruby.hpp +18 -0
  73. data/rice/detail/to_ruby.hpp +41 -3
  74. data/rice/detail/to_ruby.ipp +437 -113
  75. data/rice/global_function.hpp +0 -4
  76. data/rice/global_function.ipp +1 -2
  77. data/rice/rice.hpp +105 -22
  78. data/rice/ruby_mark.hpp +4 -3
  79. data/rice/stl.hpp +4 -0
  80. data/test/embed_ruby.cpp +4 -1
  81. data/test/extconf.rb +2 -0
  82. data/test/ruby/test_multiple_extensions_same_class.rb +14 -14
  83. data/test/test_Address_Registration_Guard.cpp +5 -0
  84. data/test/test_Array.cpp +12 -1
  85. data/test/test_Attribute.cpp +103 -21
  86. data/test/test_Builtin_Object.cpp +5 -0
  87. data/test/test_Callback.cpp +231 -0
  88. data/test/test_Class.cpp +5 -31
  89. data/test/test_Constructor.cpp +69 -6
  90. data/test/test_Data_Object.cpp +9 -4
  91. data/test/test_Data_Type.cpp +428 -64
  92. data/test/test_Director.cpp +10 -5
  93. data/test/test_Enum.cpp +152 -40
  94. data/test/test_Exception.cpp +235 -0
  95. data/test/test_File.cpp +70 -0
  96. data/test/test_From_Ruby.cpp +542 -0
  97. data/test/test_Hash.cpp +5 -0
  98. data/test/test_Identifier.cpp +5 -0
  99. data/test/test_Inheritance.cpp +6 -1
  100. data/test/test_Iterator.cpp +5 -0
  101. data/test/test_JumpException.cpp +22 -0
  102. data/test/test_Keep_Alive.cpp +6 -1
  103. data/test/test_Keep_Alive_No_Wrapper.cpp +5 -0
  104. data/test/test_Memory_Management.cpp +5 -0
  105. data/test/test_Module.cpp +118 -64
  106. data/test/test_Native_Registry.cpp +2 -33
  107. data/test/test_Object.cpp +5 -0
  108. data/test/test_Overloads.cpp +631 -0
  109. data/test/test_Ownership.cpp +67 -4
  110. data/test/test_Proc.cpp +45 -0
  111. data/test/test_Self.cpp +5 -0
  112. data/test/test_Stl_Exception.cpp +109 -0
  113. data/test/test_Stl_Map.cpp +22 -8
  114. data/test/test_Stl_Optional.cpp +5 -0
  115. data/test/test_Stl_Pair.cpp +7 -2
  116. data/test/test_Stl_Reference_Wrapper.cpp +5 -0
  117. data/test/test_Stl_SmartPointer.cpp +210 -5
  118. data/test/test_Stl_String.cpp +5 -0
  119. data/test/test_Stl_String_View.cpp +5 -0
  120. data/test/test_Stl_Type.cpp +147 -0
  121. data/test/test_Stl_Unordered_Map.cpp +18 -7
  122. data/test/test_Stl_Variant.cpp +5 -0
  123. data/test/test_Stl_Vector.cpp +130 -8
  124. data/test/test_String.cpp +5 -0
  125. data/test/test_Struct.cpp +5 -0
  126. data/test/test_Symbol.cpp +5 -0
  127. data/test/test_Template.cpp +192 -0
  128. data/test/test_To_Ruby.cpp +152 -0
  129. data/test/test_Tracking.cpp +1 -0
  130. data/test/test_Type.cpp +100 -0
  131. data/test/test_global_functions.cpp +53 -6
  132. data/test/unittest.cpp +8 -0
  133. metadata +37 -20
  134. data/lib/version.rb +0 -3
  135. data/rice/Address_Registration_Guard_defn.hpp +0 -79
  136. data/rice/Data_Object_defn.hpp +0 -84
  137. data/rice/Data_Type_defn.hpp +0 -190
  138. data/rice/Exception_defn.hpp +0 -68
  139. data/rice/HandlerRegistration.hpp +0 -15
  140. data/rice/Identifier.hpp +0 -50
  141. data/rice/Identifier.ipp +0 -29
  142. data/rice/detail/ExceptionHandler.hpp +0 -8
  143. data/rice/detail/ExceptionHandler.ipp +0 -28
  144. data/rice/detail/ExceptionHandler_defn.hpp +0 -77
  145. data/rice/detail/Jump_Tag.hpp +0 -21
  146. data/rice/detail/NativeAttribute.hpp +0 -64
  147. data/rice/detail/NativeAttribute.ipp +0 -112
  148. data/rice/detail/from_ruby_defn.hpp +0 -38
  149. data/rice/detail/to_ruby_defn.hpp +0 -48
  150. data/test/test_Jump_Tag.cpp +0 -17
  151. data/test/test_To_From_Ruby.cpp +0 -399
@@ -1,19 +1,448 @@
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 ============
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
27
+ {
28
+ public:
29
+ using RubyType_T = RubyType<T>;
30
+
31
+ static Convertible is_convertible(VALUE value)
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::Narrowable;
46
+ }
47
+ else
48
+ {
49
+ return Convertible::None;
50
+ }
51
+ }
52
+
53
+ static T convert(VALUE value)
54
+ {
55
+ return (T)protect(RubyType_T::fromRuby, value);
56
+ }
57
+ };
58
+
59
+ template<typename T>
60
+ class FromRubyFundamental<T*>
61
+ {
62
+ public:
63
+ using RubyType_T = RubyType<T>;
64
+
65
+ static Convertible is_convertible(VALUE value)
66
+ {
67
+ ruby_value_type valueType = rb_type(value);
68
+
69
+ if (RubyType_T::Exact.find(valueType) != RubyType_T::Exact.end())
70
+ {
71
+ return Convertible::Exact;
72
+ }
73
+ else if (valueType == RUBY_T_ARRAY)
74
+ {
75
+ return Convertible::Exact;
76
+ }
77
+ else if (valueType == RUBY_T_STRING)
78
+ {
79
+ // Maybe we should check for ascii8bit encoding?
80
+ //if (RB_ENCODING_IS_ASCII8BIT(value))
81
+ return Convertible::Exact;
82
+ }
83
+
84
+ return Convertible::None;
85
+ }
86
+
87
+ static std::unique_ptr<T[]> convert(VALUE value)
88
+ {
89
+ ruby_value_type valueType = rb_type(value);
90
+ switch (valueType)
91
+ {
92
+ case RUBY_T_NIL:
93
+ {
94
+ return nullptr;
95
+ break;
96
+ }
97
+ case RUBY_T_ARRAY:
98
+ {
99
+ Array array(value);
100
+ return array.pack<T>();
101
+ break;
102
+ }
103
+ case RUBY_T_STRING:
104
+ {
105
+ long size = RSTRING_LEN(value);
106
+ // Add null character to end
107
+ std::unique_ptr<T[]> dest = std::make_unique<T[]>(size + 1);
108
+ dest.get()[size] = 0;
109
+ memcpy(dest.get(), RSTRING_PTR(value), size);
110
+
111
+ return std::move(dest);
112
+ break;
113
+ }
114
+ default:
115
+ {
116
+ if (RubyType_T::Exact.find(valueType) != RubyType_T::Exact.end() ||
117
+ RubyType_T::Castable.find(valueType) != RubyType_T::Castable.end() ||
118
+ RubyType_T::Narrowable.find(valueType) != RubyType_T::Narrowable.end())
119
+ {
120
+ std::unique_ptr<T[]> dest = std::make_unique<T[]>(1);
121
+ *(dest.get()) = (T)protect(RubyType_T::fromRuby, value);
122
+ return std::move(dest);
123
+ }
124
+ else
125
+ {
126
+ std::string typeName = detail::typeName(typeid(T));
127
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected % s*)",
128
+ detail::protect(rb_obj_classname, value), typeName.c_str());
129
+ }
130
+ }
131
+ }
132
+ }
133
+ };
134
+
135
+ // =========== bool ============
136
+ template<>
137
+ class From_Ruby<bool>
138
+ {
139
+ public:
140
+ From_Ruby() = default;
141
+
142
+ explicit From_Ruby(Arg* arg) : arg_(arg)
143
+ {
144
+ }
145
+
146
+ Convertible is_convertible(VALUE value)
147
+ {
148
+ return FromRubyFundamental<bool>::is_convertible(value);
149
+ }
150
+
151
+ bool convert(VALUE value)
152
+ {
153
+ if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
154
+ {
155
+ return this->arg_->defaultValue<bool>();
156
+ }
157
+ else
158
+ {
159
+ return FromRubyFundamental<bool>::convert(value);
160
+ }
161
+ }
162
+
163
+ private:
164
+ Arg* arg_ = nullptr;
165
+ };
166
+
167
+ template<>
168
+ class From_Ruby<bool&>
169
+ {
170
+ public:
171
+ From_Ruby() = default;
172
+
173
+ explicit From_Ruby(Arg* arg) : arg_(arg)
174
+ {
175
+ }
176
+
177
+ Convertible is_convertible(VALUE value)
178
+ {
179
+ return FromRubyFundamental<bool>::is_convertible(value);
180
+ }
181
+
182
+ bool& convert(VALUE value)
183
+ {
184
+ if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
185
+ {
186
+ return this->arg_->defaultValue<bool>();
187
+ }
188
+ else
189
+ {
190
+ this->converted_ = FromRubyFundamental<bool>::convert(value);
191
+ return this->converted_;
192
+ }
193
+ }
194
+
195
+ private:
196
+ Arg* arg_ = nullptr;
197
+ bool converted_ = false;
198
+ };
199
+
200
+ template<>
201
+ class From_Ruby<bool*>
202
+ {
203
+ public:
204
+ From_Ruby() = default;
205
+
206
+ explicit From_Ruby(Arg* arg) : arg_(arg)
207
+ {
208
+ }
209
+
210
+ // Need move constructor and assignment due to std::unique_ptr
211
+ From_Ruby(From_Ruby&& other) = default;
212
+ From_Ruby& operator=(From_Ruby&& other) = default;
213
+
214
+ ~From_Ruby()
215
+ {
216
+ if (this->arg_ && this->arg_->isOwner())
217
+ {
218
+ this->converted_.release();
219
+ }
220
+ }
221
+
222
+ Convertible is_convertible(VALUE value)
223
+ {
224
+ return FromRubyFundamental<bool>::is_convertible(value);
225
+ }
226
+
227
+ bool* convert(VALUE value)
228
+ {
229
+ this->converted_ = FromRubyFundamental<bool*>::convert(value);
230
+ return this->converted_.get();
231
+ }
232
+
233
+ private:
234
+ Arg* arg_ = nullptr;
235
+ std::unique_ptr<bool[]> converted_;
236
+ };
237
+
238
+ // =========== char ============
239
+ template<>
240
+ class From_Ruby<char>
241
+ {
242
+ public:
243
+ From_Ruby() = default;
244
+
245
+ explicit From_Ruby(Arg* arg) : arg_(arg)
246
+ {
247
+ }
248
+
249
+ Convertible is_convertible(VALUE value)
250
+ {
251
+ return FromRubyFundamental<char>::is_convertible(value);
252
+ }
253
+
254
+ char convert(VALUE value)
255
+ {
256
+ if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
257
+ {
258
+ return this->arg_->defaultValue<char>();
259
+ }
260
+ else
261
+ {
262
+ return FromRubyFundamental<char>::convert(value);
263
+ }
264
+ }
265
+
266
+ private:
267
+ Arg* arg_ = nullptr;
268
+ };
269
+
270
+ template<>
271
+ class From_Ruby<char&>
272
+ {
273
+ public:
274
+ From_Ruby() = default;
275
+
276
+ explicit From_Ruby(Arg* arg) : arg_(arg)
277
+ {
278
+ }
279
+
280
+ Convertible is_convertible(VALUE value)
281
+ {
282
+ return FromRubyFundamental<char>::is_convertible(value);
283
+ }
284
+
285
+ char& convert(VALUE value)
286
+ {
287
+ if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
288
+ {
289
+ return this->arg_->defaultValue<char>();
290
+ }
291
+ else
292
+ {
293
+ this->converted_ = FromRubyFundamental<char>::convert(value);
294
+ return this->converted_;
295
+ }
296
+ }
297
+
298
+ private:
299
+ Arg* arg_ = nullptr;
300
+ char converted_ = 0;
301
+ };
302
+
303
+ template<>
304
+ class From_Ruby<char*>
305
+ {
306
+ public:
307
+ From_Ruby() = default;
308
+
309
+ explicit From_Ruby(Arg* arg) : arg_(arg)
310
+ {
311
+ }
312
+
313
+ // Need move constructor and assignment due to std::unique_ptr
314
+ From_Ruby(From_Ruby&& other) = default;
315
+ From_Ruby& operator=(From_Ruby&& other) = default;
316
+
317
+ ~From_Ruby()
318
+ {
319
+ if (this->arg_ && this->arg_->isOwner())
320
+ {
321
+ this->converted_.release();
322
+ }
323
+ }
324
+
325
+ Convertible is_convertible(VALUE value)
326
+ {
327
+ return FromRubyFundamental<char*>::is_convertible(value);
328
+ }
329
+
330
+ char* convert(VALUE value)
331
+ {
332
+ this->converted_ = FromRubyFundamental<char*>::convert(value);
333
+ return this->converted_.get();
334
+ }
335
+
336
+ private:
337
+ Arg* arg_ = nullptr;
338
+ std::unique_ptr<char[]> converted_;
339
+ };
340
+
341
+ template<>
342
+ class From_Ruby<const char*>
343
+ {
344
+ public:
345
+ From_Ruby() = default;
346
+
347
+ explicit From_Ruby(Arg* arg) : arg_(arg)
348
+ {
349
+ }
350
+
351
+ // Need move constructor and assignment due to std::unique_ptr
352
+ From_Ruby(From_Ruby&& other) = default;
353
+ From_Ruby& operator=(From_Ruby&& other) = default;
354
+
355
+ ~From_Ruby()
356
+ {
357
+ if (this->arg_ && this->arg_->isOwner())
358
+ {
359
+ this->converted_.release();
360
+ }
361
+ }
362
+
363
+ Convertible is_convertible(VALUE value)
364
+ {
365
+ return FromRubyFundamental<char*>::is_convertible(value);
366
+ }
367
+
368
+ char* convert(VALUE value)
369
+ {
370
+ this->converted_ = FromRubyFundamental<char*>::convert(value);
371
+ return this->converted_.get();
372
+ }
373
+
374
+ private:
375
+ Arg* arg_ = nullptr;
376
+ std::unique_ptr<char[]> converted_;
377
+ };
378
+
379
+ // =========== unsigned char ============
380
+ template<>
381
+ class From_Ruby<unsigned char>
382
+ {
383
+ public:
384
+ From_Ruby() = default;
385
+
386
+ explicit From_Ruby(Arg* arg) : arg_(arg)
387
+ {
388
+ }
389
+
390
+ Convertible is_convertible(VALUE value)
391
+ {
392
+ return FromRubyFundamental<unsigned char>::is_convertible(value);
393
+ }
394
+
395
+ unsigned char convert(VALUE value)
396
+ {
397
+ if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
398
+ {
399
+ return this->arg_->defaultValue<unsigned char>();
400
+ }
401
+ else
402
+ {
403
+ return FromRubyFundamental<unsigned char>::convert(value);
404
+ }
405
+ }
406
+
407
+ private:
408
+ Arg* arg_ = nullptr;
409
+ };
410
+
411
+ template<>
412
+ class From_Ruby<unsigned char&>
413
+ {
414
+ public:
415
+ From_Ruby() = default;
416
+
417
+ explicit From_Ruby(Arg* arg) : arg_(arg)
418
+ {
419
+ }
420
+
421
+ Convertible is_convertible(VALUE value)
422
+ {
423
+ return FromRubyFundamental<unsigned char>::is_convertible(value);
424
+ }
425
+
426
+ unsigned char& convert(VALUE value)
427
+ {
428
+ if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
429
+ {
430
+ return this->arg_->defaultValue<unsigned char>();
431
+ }
432
+ else
433
+ {
434
+ this->converted_ = FromRubyFundamental<unsigned char>::convert(value);
435
+ return this->converted_;
436
+ }
437
+ }
438
+
439
+ private:
440
+ Arg* arg_ = nullptr;
441
+ unsigned char converted_ = 0;
442
+ };
443
+
15
444
  template<>
16
- class From_Ruby<short>
445
+ class From_Ruby<unsigned char*>
17
446
  {
18
447
  public:
19
448
  From_Ruby() = default;
@@ -22,29 +451,37 @@ namespace Rice::detail
22
451
  {
23
452
  }
24
453
 
25
- bool is_convertible(VALUE value)
26
- {
27
- return rb_type(value) == RUBY_T_FIXNUM;
28
- }
454
+ // Need move constructor and assignment due to std::unique_ptr
455
+ From_Ruby(From_Ruby&& other) = default;
456
+ From_Ruby& operator=(From_Ruby&& other) = default;
29
457
 
30
- short convert(VALUE value)
458
+ ~From_Ruby()
31
459
  {
32
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
33
- {
34
- return this->arg_->defaultValue<short>();
35
- }
36
- else
460
+ if (this->arg_ && this->arg_->isOwner())
37
461
  {
38
- return protect(rb_num2short_inline, value);
462
+ this->converted_.release();
39
463
  }
40
464
  }
41
-
465
+
466
+ Convertible is_convertible(VALUE value)
467
+ {
468
+ return FromRubyFundamental<unsigned char*>::is_convertible(value);
469
+ }
470
+
471
+ unsigned char* convert(VALUE value)
472
+ {
473
+ this->converted_ = FromRubyFundamental<unsigned char*>::convert(value);
474
+ return this->converted_.get();
475
+ }
476
+
42
477
  private:
43
478
  Arg* arg_ = nullptr;
479
+ std::unique_ptr<unsigned char[]> converted_;
44
480
  };
45
481
 
482
+ // =========== signed char ============
46
483
  template<>
47
- class From_Ruby<short&>
484
+ class From_Ruby<signed char>
48
485
  {
49
486
  public:
50
487
  From_Ruby() = default;
@@ -53,58 +490,68 @@ namespace Rice::detail
53
490
  {
54
491
  }
55
492
 
56
- bool is_convertible(VALUE value)
493
+ Convertible is_convertible(VALUE value)
57
494
  {
58
- return rb_type(value) == RUBY_T_FIXNUM;
495
+ return FromRubyFundamental<signed char>::is_convertible(value);
59
496
  }
60
497
 
61
- short& convert(VALUE value)
498
+ signed char convert(VALUE value)
62
499
  {
63
500
  if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
64
501
  {
65
- return this->arg_->defaultValue<short>();
502
+ return this->arg_->defaultValue<signed char>();
66
503
  }
67
504
  else
68
505
  {
69
- this->converted_ = protect(rb_num2short_inline, value);
70
- return this->converted_;
506
+ return FromRubyFundamental<signed char>::convert(value);
71
507
  }
72
508
  }
73
509
 
74
510
  private:
75
511
  Arg* arg_ = nullptr;
76
- short converted_ = 0;
77
512
  };
78
513
 
79
514
  template<>
80
- class From_Ruby<short*>
515
+ class From_Ruby<signed char*>
81
516
  {
82
517
  public:
83
- bool is_convertible(VALUE value)
518
+ From_Ruby() = default;
519
+
520
+ explicit From_Ruby(Arg* arg) : arg_(arg)
84
521
  {
85
- return rb_type(value) == RUBY_T_FIXNUM;
86
522
  }
87
523
 
88
- short* convert(VALUE value)
524
+ // Need move constructor and assignment due to std::unique_ptr
525
+ From_Ruby(From_Ruby&& other) = default;
526
+ From_Ruby& operator=(From_Ruby&& other) = default;
527
+
528
+ ~From_Ruby()
89
529
  {
90
- if (value == Qnil)
91
- {
92
- return nullptr;
93
- }
94
- else
530
+ if (this->arg_ && this->arg_->isOwner())
95
531
  {
96
- this->converted_ = protect(rb_num2short_inline, value);
97
- return &this->converted_;
532
+ this->converted_.release();
98
533
  }
99
534
  }
100
535
 
536
+ Convertible is_convertible(VALUE value)
537
+ {
538
+ return FromRubyFundamental<signed char*>::is_convertible(value);
539
+ }
540
+
541
+ signed char* convert(VALUE value)
542
+ {
543
+ this->converted_ = FromRubyFundamental<signed char*>::convert(value);
544
+ return this->converted_.get();
545
+ }
546
+
101
547
  private:
102
- short converted_ = 0;
548
+ Arg* arg_ = nullptr;
549
+ std::unique_ptr<signed char[]> converted_;
103
550
  };
104
551
 
105
- // =========== int ============
552
+ // =========== double ============
106
553
  template<>
107
- class From_Ruby<int>
554
+ class From_Ruby<double>
108
555
  {
109
556
  public:
110
557
  From_Ruby() = default;
@@ -113,29 +560,29 @@ namespace Rice::detail
113
560
  {
114
561
  }
115
562
 
116
- bool is_convertible(VALUE value)
563
+ Convertible is_convertible(VALUE value)
117
564
  {
118
- return rb_type(value) == RUBY_T_FIXNUM;
565
+ return FromRubyFundamental<double>::is_convertible(value);
119
566
  }
120
567
 
121
- int convert(VALUE value)
568
+ double convert(VALUE value)
122
569
  {
123
570
  if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
124
571
  {
125
- return this->arg_->defaultValue<int>();
572
+ return this->arg_->defaultValue<double>();
126
573
  }
127
574
  else
128
575
  {
129
- return (int)protect(rb_num2long_inline, value);
576
+ return FromRubyFundamental<double>::convert(value);
130
577
  }
131
578
  }
132
-
579
+
133
580
  private:
134
581
  Arg* arg_ = nullptr;
135
582
  };
136
583
 
137
584
  template<>
138
- class From_Ruby<int&>
585
+ class From_Ruby<double&>
139
586
  {
140
587
  public:
141
588
  From_Ruby() = default;
@@ -144,58 +591,70 @@ namespace Rice::detail
144
591
  {
145
592
  }
146
593
 
147
- bool is_convertible(VALUE value)
594
+ Convertible is_convertible(VALUE value)
148
595
  {
149
- return rb_type(value) == RUBY_T_FIXNUM;
596
+ return FromRubyFundamental<double>::is_convertible(value);
150
597
  }
151
598
 
152
- int& convert(VALUE value)
599
+ double& convert(VALUE value)
153
600
  {
154
601
  if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
155
602
  {
156
- return this->arg_->defaultValue<int>();
603
+ return this->arg_->defaultValue<double>();
157
604
  }
158
605
  else
159
606
  {
160
- this->converted_ = (int)protect(rb_num2long_inline, value);
607
+ this->converted_ = FromRubyFundamental<double>::convert(value);
161
608
  return this->converted_;
162
609
  }
163
610
  }
164
611
 
165
612
  private:
166
613
  Arg* arg_ = nullptr;
167
- int converted_ = 0;
614
+ double converted_;
168
615
  };
169
616
 
170
617
  template<>
171
- class From_Ruby<int*>
618
+ class From_Ruby<double*>
172
619
  {
173
620
  public:
174
- bool is_convertible(VALUE value)
621
+ From_Ruby() = default;
622
+
623
+ explicit From_Ruby(Arg* arg) : arg_(arg)
175
624
  {
176
- return rb_type(value) == RUBY_T_FIXNUM;
177
625
  }
178
626
 
179
- int* convert(VALUE value)
627
+ // Need move constructor and assignment due to std::unique_ptr
628
+ From_Ruby(From_Ruby&& other) = default;
629
+ From_Ruby& operator=(From_Ruby&& other) = default;
630
+
631
+ ~From_Ruby()
180
632
  {
181
- if (value == Qnil)
182
- {
183
- return nullptr;
184
- }
185
- else
633
+ if (this->arg_ && this->arg_->isOwner())
186
634
  {
187
- this->converted_ = (int)protect(rb_num2long_inline, value);
188
- return &this->converted_;
635
+ this->converted_.release();
189
636
  }
190
637
  }
191
638
 
639
+ Convertible is_convertible(VALUE value)
640
+ {
641
+ return FromRubyFundamental<double*>::is_convertible(value);
642
+ }
643
+
644
+ double* convert(VALUE value)
645
+ {
646
+ this->converted_ = FromRubyFundamental<double*>::convert(value);
647
+ return this->converted_.get();
648
+ }
649
+
192
650
  private:
193
- int converted_;
651
+ Arg* arg_ = nullptr;
652
+ std::unique_ptr<double[]> converted_;
194
653
  };
195
654
 
196
- // =========== long ============
655
+ // =========== float ============
197
656
  template<>
198
- class From_Ruby<long>
657
+ class From_Ruby<float>
199
658
  {
200
659
  public:
201
660
  From_Ruby() = default;
@@ -204,29 +663,29 @@ namespace Rice::detail
204
663
  {
205
664
  }
206
665
 
207
- bool is_convertible(VALUE value)
666
+ Convertible is_convertible(VALUE value)
208
667
  {
209
- return rb_type(value) == RUBY_T_FIXNUM;
668
+ return FromRubyFundamental<float>::is_convertible(value);
210
669
  }
211
670
 
212
- long convert(VALUE value)
671
+ float convert(VALUE value)
213
672
  {
214
673
  if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
215
674
  {
216
- return this->arg_->defaultValue<long>();
675
+ return this->arg_->defaultValue<float>();
217
676
  }
218
677
  else
219
678
  {
220
- return protect(rb_num2long_inline, value);
679
+ return FromRubyFundamental<float>::convert(value);
221
680
  }
222
681
  }
223
-
682
+
224
683
  private:
225
684
  Arg* arg_ = nullptr;
226
685
  };
227
686
 
228
687
  template<>
229
- class From_Ruby<long&>
688
+ class From_Ruby<float&>
230
689
  {
231
690
  public:
232
691
  From_Ruby() = default;
@@ -235,58 +694,70 @@ namespace Rice::detail
235
694
  {
236
695
  }
237
696
 
238
- bool is_convertible(VALUE value)
697
+ Convertible is_convertible(VALUE value)
239
698
  {
240
- return rb_type(value) == RUBY_T_FIXNUM;
699
+ return FromRubyFundamental<float>::is_convertible(value);
241
700
  }
242
701
 
243
- long& convert(VALUE value)
702
+ float& convert(VALUE value)
244
703
  {
245
704
  if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
246
705
  {
247
- return this->arg_->defaultValue<long>();
706
+ return this->arg_->defaultValue<float>();
248
707
  }
249
708
  else
250
709
  {
251
- this->converted_ = protect(rb_num2long_inline, value);
710
+ this->converted_ = FromRubyFundamental<float>::convert(value);
252
711
  return this->converted_;
253
712
  }
254
713
  }
255
714
 
256
715
  private:
257
716
  Arg* arg_ = nullptr;
258
- long converted_ = 0;
717
+ float converted_;
259
718
  };
260
719
 
261
720
  template<>
262
- class From_Ruby<long*>
721
+ class From_Ruby<float*>
263
722
  {
264
723
  public:
265
- bool is_convertible(VALUE value)
724
+ From_Ruby() = default;
725
+
726
+ explicit From_Ruby(Arg* arg) : arg_(arg)
266
727
  {
267
- return rb_type(value) == RUBY_T_FIXNUM;
268
728
  }
269
729
 
270
- long* convert(VALUE value)
730
+ // Need move constructor and assignment due to std::unique_ptr
731
+ From_Ruby(From_Ruby&& other) = default;
732
+ From_Ruby& operator=(From_Ruby&& other) = default;
733
+
734
+ ~From_Ruby()
271
735
  {
272
- if (value == Qnil)
273
- {
274
- return nullptr;
275
- }
276
- else
736
+ if (this->arg_ && this->arg_->isOwner())
277
737
  {
278
- this->converted_ = protect(rb_num2long_inline, value);
279
- return &this->converted_;
738
+ this->converted_.release();
280
739
  }
281
740
  }
282
741
 
742
+ Convertible is_convertible(VALUE value)
743
+ {
744
+ return FromRubyFundamental<float*>::is_convertible(value);
745
+ }
746
+
747
+ float* convert(VALUE value)
748
+ {
749
+ this->converted_ = FromRubyFundamental<float*>::convert(value);
750
+ return this->converted_.get();
751
+ }
752
+
283
753
  private:
284
- long converted_ = 0;
754
+ Arg* arg_ = nullptr;
755
+ std::unique_ptr<float[]> converted_;
285
756
  };
286
757
 
287
- // =========== long long ============
758
+ // =========== int ============
288
759
  template<>
289
- class From_Ruby<long long>
760
+ class From_Ruby<int>
290
761
  {
291
762
  public:
292
763
  From_Ruby() = default;
@@ -295,20 +766,31 @@ namespace Rice::detail
295
766
  {
296
767
  }
297
768
 
298
- bool is_convertible(VALUE value)
769
+ Convertible is_convertible(VALUE value)
299
770
  {
300
- return rb_type(value) == RUBY_T_FIXNUM;
771
+ Convertible result = FromRubyFundamental<int>::is_convertible(value);
772
+
773
+ // Is this an enum? If so we want to support converting it to an integer
774
+ if (result == Convertible::None && rb_type(value) == RUBY_T_DATA)
775
+ {
776
+ static ID id = protect(rb_intern, "to_int");
777
+ if (protect(rb_respond_to, value, id))
778
+ {
779
+ result = Convertible::Cast;
780
+ }
781
+ }
782
+ return result;
301
783
  }
302
784
 
303
- long long convert(VALUE value)
785
+ int convert(VALUE value)
304
786
  {
305
787
  if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
306
788
  {
307
- return this->arg_->defaultValue<long long>();
789
+ return this->arg_->defaultValue<int>();
308
790
  }
309
791
  else
310
792
  {
311
- return protect(rb_num2ll_inline, value);
793
+ return FromRubyFundamental<int>::convert(value);
312
794
  }
313
795
  }
314
796
 
@@ -317,7 +799,7 @@ namespace Rice::detail
317
799
  };
318
800
 
319
801
  template<>
320
- class From_Ruby<long long&>
802
+ class From_Ruby<int&>
321
803
  {
322
804
  public:
323
805
  From_Ruby() = default;
@@ -326,58 +808,70 @@ namespace Rice::detail
326
808
  {
327
809
  }
328
810
 
329
- bool is_convertible(VALUE value)
811
+ Convertible is_convertible(VALUE value)
330
812
  {
331
- return rb_type(value) == RUBY_T_FIXNUM;
813
+ return FromRubyFundamental<int>::is_convertible(value);
332
814
  }
333
815
 
334
- long long& convert(VALUE value)
816
+ int& convert(VALUE value)
335
817
  {
336
818
  if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
337
819
  {
338
- return this->arg_->defaultValue<long long>();
820
+ return this->arg_->defaultValue<int>();
339
821
  }
340
822
  else
341
823
  {
342
- this->converted_ = protect(rb_num2ll_inline, value);
824
+ this->converted_ = FromRubyFundamental<int>::convert(value);
343
825
  return this->converted_;
344
826
  }
345
827
  }
346
828
 
347
829
  private:
348
830
  Arg* arg_ = nullptr;
349
- long long converted_ = 0;
831
+ int converted_ = 0;
350
832
  };
351
833
 
352
834
  template<>
353
- class From_Ruby<long long*>
835
+ class From_Ruby<int*>
354
836
  {
355
837
  public:
356
- bool is_convertible(VALUE value)
838
+ From_Ruby() = default;
839
+
840
+ explicit From_Ruby(Arg* arg) : arg_(arg)
357
841
  {
358
- return rb_type(value) == RUBY_T_FIXNUM;
359
842
  }
360
843
 
361
- long long* convert(VALUE value)
844
+ // Need move constructor and assignment due to std::unique_ptr
845
+ From_Ruby(From_Ruby&& other) = default;
846
+ From_Ruby& operator=(From_Ruby&& other) = default;
847
+
848
+ ~From_Ruby()
362
849
  {
363
- if (value == Qnil)
364
- {
365
- return nullptr;
366
- }
367
- else
850
+ if (this->arg_ && this->arg_->isOwner())
368
851
  {
369
- this->converted_ = protect(rb_num2ll_inline, value);
370
- return &this->converted_;
852
+ this->converted_.release();
371
853
  }
372
854
  }
373
855
 
856
+ Convertible is_convertible(VALUE value)
857
+ {
858
+ return FromRubyFundamental<int*>::is_convertible(value);
859
+ }
860
+
861
+ int* convert(VALUE value)
862
+ {
863
+ this->converted_ = FromRubyFundamental<int*>::convert(value);
864
+ return this->converted_.get();
865
+ }
866
+
374
867
  private:
375
- long long converted_ = 0;
868
+ Arg* arg_ = nullptr;
869
+ std::unique_ptr<int[]> converted_;
376
870
  };
377
871
 
378
- // =========== unsigned short ============
872
+ // =========== unsigned int ============
379
873
  template<>
380
- class From_Ruby<unsigned short>
874
+ class From_Ruby<unsigned int>
381
875
  {
382
876
  public:
383
877
  From_Ruby() = default;
@@ -386,29 +880,29 @@ namespace Rice::detail
386
880
  {
387
881
  }
388
882
 
389
- bool is_convertible(VALUE value)
883
+ Convertible is_convertible(VALUE value)
390
884
  {
391
- return rb_type(value) == RUBY_T_FIXNUM;
885
+ return FromRubyFundamental<unsigned int>::is_convertible(value);
392
886
  }
393
887
 
394
- unsigned short convert(VALUE value)
888
+ unsigned int convert(VALUE value)
395
889
  {
396
890
  if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
397
891
  {
398
- return this->arg_->defaultValue<unsigned short>();
892
+ return this->arg_->defaultValue<unsigned int>();
399
893
  }
400
894
  else
401
895
  {
402
- return protect(rb_num2ushort, value);
896
+ return FromRubyFundamental<unsigned int>::convert(value);
403
897
  }
404
898
  }
405
-
899
+
406
900
  private:
407
901
  Arg* arg_ = nullptr;
408
902
  };
409
903
 
410
904
  template<>
411
- class From_Ruby<unsigned short&>
905
+ class From_Ruby<unsigned int&>
412
906
  {
413
907
  public:
414
908
  From_Ruby() = default;
@@ -417,58 +911,70 @@ namespace Rice::detail
417
911
  {
418
912
  }
419
913
 
420
- bool is_convertible(VALUE value)
914
+ Convertible is_convertible(VALUE value)
421
915
  {
422
- return rb_type(value) == RUBY_T_FIXNUM;
916
+ return FromRubyFundamental<unsigned int>::is_convertible(value);
423
917
  }
424
918
 
425
- unsigned short& convert(VALUE value)
919
+ unsigned int& convert(VALUE value)
426
920
  {
427
921
  if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
428
922
  {
429
- return this->arg_->defaultValue<unsigned short>();
923
+ return this->arg_->defaultValue<unsigned int>();
430
924
  }
431
925
  else
432
926
  {
433
- this->converted_ = protect(rb_num2ushort, value);
927
+ this->converted_ = FromRubyFundamental<unsigned int>::convert(value);
434
928
  return this->converted_;
435
929
  }
436
930
  }
437
931
 
438
932
  private:
439
933
  Arg* arg_ = nullptr;
440
- unsigned short converted_ = 0;
934
+ unsigned int converted_ = 0;
441
935
  };
442
936
 
443
937
  template<>
444
- class From_Ruby<unsigned short*>
938
+ class From_Ruby<unsigned int*>
445
939
  {
446
940
  public:
447
- bool is_convertible(VALUE value)
941
+ From_Ruby() = default;
942
+
943
+ explicit From_Ruby(Arg* arg) : arg_(arg)
448
944
  {
449
- return rb_type(value) == RUBY_T_FIXNUM;
450
945
  }
451
946
 
452
- unsigned short* convert(VALUE value)
947
+ // Need move constructor and assignment due to std::unique_ptr
948
+ From_Ruby(From_Ruby&& other) = default;
949
+ From_Ruby& operator=(From_Ruby&& other) = default;
950
+
951
+ ~From_Ruby()
453
952
  {
454
- if (value == Qnil)
455
- {
456
- return nullptr;
457
- }
458
- else
953
+ if (this->arg_ && this->arg_->isOwner())
459
954
  {
460
- this->converted_ = protect(rb_num2ushort, value);
461
- return &this->converted_;
955
+ this->converted_.release();
462
956
  }
463
957
  }
464
958
 
959
+ Convertible is_convertible(VALUE value)
960
+ {
961
+ return FromRubyFundamental<unsigned int*>::is_convertible(value);
962
+ }
963
+
964
+ unsigned int* convert(VALUE value)
965
+ {
966
+ this->converted_ = FromRubyFundamental<unsigned int*>::convert(value);
967
+ return this->converted_.get();
968
+ }
969
+
465
970
  private:
466
- unsigned short converted_ = 0;
971
+ Arg* arg_ = nullptr;
972
+ std::unique_ptr<unsigned int[]> converted_;;
467
973
  };
468
974
 
469
- // =========== unsigned int ============
975
+ // =========== long ============
470
976
  template<>
471
- class From_Ruby<unsigned int>
977
+ class From_Ruby<long>
472
978
  {
473
979
  public:
474
980
  From_Ruby() = default;
@@ -477,20 +983,20 @@ namespace Rice::detail
477
983
  {
478
984
  }
479
985
 
480
- bool is_convertible(VALUE value)
986
+ Convertible is_convertible(VALUE value)
481
987
  {
482
- return rb_type(value) == RUBY_T_FIXNUM;
988
+ return FromRubyFundamental<long>::is_convertible(value);
483
989
  }
484
990
 
485
- unsigned int convert(VALUE value)
991
+ long convert(VALUE value)
486
992
  {
487
993
  if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
488
994
  {
489
- return this->arg_->defaultValue<unsigned int>();
995
+ return this->arg_->defaultValue<long>();
490
996
  }
491
997
  else
492
998
  {
493
- return (unsigned int)protect(rb_num2ulong_inline, value);
999
+ return FromRubyFundamental<long>::convert(value);
494
1000
  }
495
1001
  }
496
1002
 
@@ -499,7 +1005,7 @@ namespace Rice::detail
499
1005
  };
500
1006
 
501
1007
  template<>
502
- class From_Ruby<unsigned int&>
1008
+ class From_Ruby<long&>
503
1009
  {
504
1010
  public:
505
1011
  From_Ruby() = default;
@@ -508,53 +1014,65 @@ namespace Rice::detail
508
1014
  {
509
1015
  }
510
1016
 
511
- bool is_convertible(VALUE value)
1017
+ Convertible is_convertible(VALUE value)
512
1018
  {
513
- return rb_type(value) == RUBY_T_FIXNUM;
1019
+ return FromRubyFundamental<long>::is_convertible(value);
514
1020
  }
515
1021
 
516
- unsigned int& convert(VALUE value)
1022
+ long& convert(VALUE value)
517
1023
  {
518
1024
  if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
519
1025
  {
520
- return this->arg_->defaultValue<unsigned int>();
1026
+ return this->arg_->defaultValue<long>();
521
1027
  }
522
1028
  else
523
1029
  {
524
- this->converted_ = (unsigned int)protect(rb_num2ulong_inline, value);
1030
+ this->converted_ = FromRubyFundamental<long>::convert(value);
525
1031
  return this->converted_;
526
1032
  }
527
1033
  }
528
1034
 
529
1035
  private:
530
1036
  Arg* arg_ = nullptr;
531
- unsigned int converted_ = 0;
1037
+ long converted_ = 0;
532
1038
  };
533
1039
 
534
1040
  template<>
535
- class From_Ruby<unsigned int*>
1041
+ class From_Ruby<long*>
536
1042
  {
537
1043
  public:
538
- bool is_convertible(VALUE value)
1044
+ From_Ruby() = default;
1045
+
1046
+ explicit From_Ruby(Arg* arg) : arg_(arg)
539
1047
  {
540
- return rb_type(value) == RUBY_T_FIXNUM;
541
1048
  }
542
1049
 
543
- unsigned int* convert(VALUE value)
1050
+ // Need move constructor and assignment due to std::unique_ptr
1051
+ From_Ruby(From_Ruby&& other) = default;
1052
+ From_Ruby& operator=(From_Ruby&& other) = default;
1053
+
1054
+ ~From_Ruby()
544
1055
  {
545
- if (value == Qnil)
546
- {
547
- return nullptr;
548
- }
549
- else
1056
+ if (this->arg_ && this->arg_->isOwner())
550
1057
  {
551
- this->converted_ = (unsigned int)protect(rb_num2ulong_inline, value);
552
- return &this->converted_;
1058
+ this->converted_.release();
553
1059
  }
554
1060
  }
555
1061
 
1062
+ Convertible is_convertible(VALUE value)
1063
+ {
1064
+ return FromRubyFundamental<long*>::is_convertible(value);
1065
+ }
1066
+
1067
+ long* convert(VALUE value)
1068
+ {
1069
+ this->converted_ = FromRubyFundamental<long*>::convert(value);
1070
+ return this->converted_.get();
1071
+ }
1072
+
556
1073
  private:
557
- unsigned int converted_ = 0;
1074
+ Arg* arg_ = nullptr;
1075
+ std::unique_ptr<long[]> converted_;
558
1076
  };
559
1077
 
560
1078
  // =========== unsigned long ============
@@ -568,9 +1086,9 @@ namespace Rice::detail
568
1086
  {
569
1087
  }
570
1088
 
571
- bool is_convertible(VALUE value)
1089
+ Convertible is_convertible(VALUE value)
572
1090
  {
573
- return rb_type(value) == RUBY_T_FIXNUM;
1091
+ return FromRubyFundamental<unsigned long>::is_convertible(value);
574
1092
  }
575
1093
 
576
1094
  unsigned long convert(VALUE value)
@@ -585,10 +1103,10 @@ namespace Rice::detail
585
1103
  }
586
1104
  else
587
1105
  {
588
- return protect(rb_num2ulong_inline, value);
1106
+ return FromRubyFundamental<unsigned long>::convert(value);
589
1107
  }
590
1108
  }
591
-
1109
+
592
1110
  private:
593
1111
  Arg* arg_ = nullptr;
594
1112
  };
@@ -603,9 +1121,9 @@ namespace Rice::detail
603
1121
  {
604
1122
  }
605
1123
 
606
- bool is_convertible(VALUE value)
1124
+ Convertible is_convertible(VALUE value)
607
1125
  {
608
- return rb_type(value) == RUBY_T_FIXNUM;
1126
+ return FromRubyFundamental<unsigned long>::is_convertible(value);
609
1127
  }
610
1128
 
611
1129
  unsigned long& convert(VALUE value)
@@ -616,7 +1134,7 @@ namespace Rice::detail
616
1134
  }
617
1135
  else
618
1136
  {
619
- this->converted_ = protect(rb_num2ulong_inline, value);
1137
+ this->converted_ = FromRubyFundamental<unsigned long>::convert(value);
620
1138
  return this->converted_;
621
1139
  }
622
1140
  }
@@ -630,26 +1148,38 @@ namespace Rice::detail
630
1148
  class From_Ruby<unsigned long*>
631
1149
  {
632
1150
  public:
633
- bool is_convertible(VALUE value)
1151
+ From_Ruby() = default;
1152
+
1153
+ explicit From_Ruby(Arg* arg) : arg_(arg)
634
1154
  {
635
- return rb_type(value) == RUBY_T_FIXNUM;
636
1155
  }
637
1156
 
638
- unsigned long* convert(VALUE value)
1157
+ // Need move constructor and assignment due to std::unique_ptr
1158
+ From_Ruby(From_Ruby&& other) = default;
1159
+ From_Ruby& operator=(From_Ruby&& other) = default;
1160
+
1161
+ ~From_Ruby()
639
1162
  {
640
- if (value == Qnil)
641
- {
642
- return nullptr;
643
- }
644
- else
1163
+ if (this->arg_ && this->arg_->isOwner())
645
1164
  {
646
- this->converted_ = protect(rb_num2ulong_inline, value);
647
- return &this->converted_;
1165
+ this->converted_.release();
648
1166
  }
649
1167
  }
650
1168
 
1169
+ Convertible is_convertible(VALUE value)
1170
+ {
1171
+ return FromRubyFundamental<unsigned long*>::is_convertible(value);
1172
+ }
1173
+
1174
+ unsigned long* convert(VALUE value)
1175
+ {
1176
+ this->converted_ = FromRubyFundamental<unsigned long*>::convert(value);
1177
+ return this->converted_.get();
1178
+ }
1179
+
651
1180
  private:
652
- unsigned long converted_ = 0;
1181
+ Arg* arg_ = nullptr;
1182
+ std::unique_ptr<unsigned long[]> converted_;
653
1183
  };
654
1184
 
655
1185
  // =========== unsigned long long ============
@@ -663,9 +1193,9 @@ namespace Rice::detail
663
1193
  {
664
1194
  }
665
1195
 
666
- bool is_convertible(VALUE value)
1196
+ Convertible is_convertible(VALUE value)
667
1197
  {
668
- return rb_type(value) == RUBY_T_FIXNUM;
1198
+ return FromRubyFundamental<unsigned long long>::is_convertible(value);
669
1199
  }
670
1200
 
671
1201
  unsigned long long convert(VALUE value)
@@ -680,10 +1210,10 @@ namespace Rice::detail
680
1210
  }
681
1211
  else
682
1212
  {
683
- return protect(rb_num2ull, value);
1213
+ return FromRubyFundamental<unsigned long long>::convert(value);
684
1214
  }
685
1215
  }
686
-
1216
+
687
1217
  private:
688
1218
  Arg* arg_ = nullptr;
689
1219
  };
@@ -698,9 +1228,9 @@ namespace Rice::detail
698
1228
  {
699
1229
  }
700
1230
 
701
- bool is_convertible(VALUE value)
1231
+ Convertible is_convertible(VALUE value)
702
1232
  {
703
- return rb_type(value) == RUBY_T_FIXNUM;
1233
+ return FromRubyFundamental<unsigned long long>::is_convertible(value);
704
1234
  }
705
1235
 
706
1236
  unsigned long long& convert(VALUE value)
@@ -711,7 +1241,7 @@ namespace Rice::detail
711
1241
  }
712
1242
  else
713
1243
  {
714
- this->converted_ = protect(rb_num2ull, value);
1244
+ this->converted_ = FromRubyFundamental<unsigned long long>::convert(value);
715
1245
  return this->converted_;
716
1246
  }
717
1247
  }
@@ -725,9 +1255,27 @@ namespace Rice::detail
725
1255
  class From_Ruby<unsigned long long*>
726
1256
  {
727
1257
  public:
728
- bool is_convertible(VALUE value)
1258
+ From_Ruby() = default;
1259
+
1260
+ explicit From_Ruby(Arg* arg) : arg_(arg)
1261
+ {
1262
+ }
1263
+
1264
+ // Need move constructor and assignment due to std::unique_ptr
1265
+ From_Ruby(From_Ruby&& other) = default;
1266
+ From_Ruby& operator=(From_Ruby&& other) = default;
1267
+
1268
+ ~From_Ruby()
1269
+ {
1270
+ if (this->arg_ && this->arg_->isOwner())
1271
+ {
1272
+ this->converted_.release();
1273
+ }
1274
+ }
1275
+
1276
+ Convertible is_convertible(VALUE value)
729
1277
  {
730
- return rb_type(value) == RUBY_T_FIXNUM;
1278
+ return FromRubyFundamental<unsigned long long*>::is_convertible(value);
731
1279
  }
732
1280
 
733
1281
  unsigned long long* convert(VALUE value)
@@ -738,18 +1286,19 @@ namespace Rice::detail
738
1286
  }
739
1287
  else
740
1288
  {
741
- this->converted_ = protect(rb_num2ull, value);
742
- return &this->converted_;
1289
+ this->converted_ = FromRubyFundamental<unsigned long long*>::convert(value);
1290
+ return this->converted_.get();
743
1291
  }
744
1292
  }
745
1293
 
746
1294
  private:
747
- unsigned long long converted_ = 0;
1295
+ Arg* arg_ = nullptr;
1296
+ std::unique_ptr<unsigned long long[]> converted_;
748
1297
  };
749
1298
 
750
- // =========== bool ============
1299
+ // =========== long long ============
751
1300
  template<>
752
- class From_Ruby<bool>
1301
+ class From_Ruby<long long>
753
1302
  {
754
1303
  public:
755
1304
  From_Ruby() = default;
@@ -758,23 +1307,20 @@ namespace Rice::detail
758
1307
  {
759
1308
  }
760
1309
 
761
- bool is_convertible(VALUE value)
1310
+ Convertible is_convertible(VALUE value)
762
1311
  {
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;
1312
+ return FromRubyFundamental<long long>::is_convertible(value);
767
1313
  }
768
1314
 
769
- bool convert(VALUE value)
1315
+ long long convert(VALUE value)
770
1316
  {
771
1317
  if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
772
1318
  {
773
- return this->arg_->defaultValue<bool>();
1319
+ return this->arg_->defaultValue<long long>();
774
1320
  }
775
1321
  else
776
1322
  {
777
- return RTEST(value);
1323
+ return FromRubyFundamental<long long>::convert(value);
778
1324
  }
779
1325
  }
780
1326
 
@@ -783,7 +1329,7 @@ namespace Rice::detail
783
1329
  };
784
1330
 
785
1331
  template<>
786
- class From_Ruby<bool&>
1332
+ class From_Ruby<long long&>
787
1333
  {
788
1334
  public:
789
1335
  From_Ruby() = default;
@@ -792,125 +1338,70 @@ namespace Rice::detail
792
1338
  {
793
1339
  }
794
1340
 
795
- bool is_convertible(VALUE value)
1341
+ Convertible is_convertible(VALUE value)
796
1342
  {
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;
1343
+ return FromRubyFundamental<long long>::is_convertible(value);
801
1344
  }
802
1345
 
803
- bool& convert(VALUE value)
1346
+ long long& convert(VALUE value)
804
1347
  {
805
1348
  if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
806
1349
  {
807
- return this->arg_->defaultValue<bool>();
1350
+ return this->arg_->defaultValue<long long>();
808
1351
  }
809
1352
  else
810
1353
  {
811
- this->converted_ = RTEST(value);
1354
+ this->converted_ = FromRubyFundamental<long long>::convert(value);
812
1355
  return this->converted_;
813
1356
  }
814
1357
  }
815
1358
 
816
1359
  private:
817
1360
  Arg* arg_ = nullptr;
818
- bool converted_ = false;
1361
+ long long converted_ = 0;
819
1362
  };
820
1363
 
821
1364
  template<>
822
- class From_Ruby<bool*>
1365
+ class From_Ruby<long long*>
823
1366
  {
824
1367
  public:
825
- bool is_convertible(VALUE value)
826
- {
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
- }
1368
+ From_Ruby() = default;
832
1369
 
833
- bool* convert(VALUE value)
1370
+ explicit From_Ruby(Arg* arg) : arg_(arg)
834
1371
  {
835
- if (value == Qnil)
836
- {
837
- return nullptr;
838
- }
839
- else
840
- {
841
- this->converted_ = RTEST(value);
842
- return &this->converted_;
843
- }
844
1372
  }
845
1373
 
846
- private:
847
- bool converted_ = false;
848
- };
1374
+ // Need move constructor and assignment due to std::unique_ptr
1375
+ From_Ruby(From_Ruby&& other) = default;
1376
+ From_Ruby& operator=(From_Ruby&& other) = default;
849
1377
 
850
- // =========== char ============
851
- template<typename T>
852
- inline T charFromRuby(VALUE value)
853
- {
854
- switch (rb_type(value))
1378
+ ~From_Ruby()
855
1379
  {
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:
1380
+ if (this->arg_ && this->arg_->isOwner())
874
1381
  {
875
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
876
- detail::protect(rb_obj_classname, value), "char type");
1382
+ this->converted_.release();
877
1383
  }
878
1384
  }
879
- }
880
-
881
- template<>
882
- class From_Ruby<char>
883
- {
884
- public:
885
- From_Ruby() = default;
886
1385
 
887
- explicit From_Ruby(Arg* arg) : arg_(arg)
1386
+ Convertible is_convertible(VALUE value)
888
1387
  {
1388
+ return FromRubyFundamental<long long*>::is_convertible(value);
889
1389
  }
890
1390
 
891
- bool is_convertible(VALUE value)
1391
+ long long* convert(VALUE value)
892
1392
  {
893
- return rb_type(value) == RUBY_T_STRING;
1393
+ this->converted_ = FromRubyFundamental<long long*>::convert(value);
1394
+ return this->converted_.get();
894
1395
  }
895
1396
 
896
- char convert(VALUE value)
897
- {
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
- }
906
- }
907
-
908
1397
  private:
909
1398
  Arg* arg_ = nullptr;
1399
+ std::unique_ptr<long long[]> converted_;
910
1400
  };
911
1401
 
1402
+ // =========== short ============
912
1403
  template<>
913
- class From_Ruby<char&>
1404
+ class From_Ruby<short>
914
1405
  {
915
1406
  public:
916
1407
  From_Ruby() = default;
@@ -919,79 +1410,62 @@ namespace Rice::detail
919
1410
  {
920
1411
  }
921
1412
 
922
- bool is_convertible(VALUE value)
1413
+ Convertible is_convertible(VALUE value)
923
1414
  {
924
- return rb_type(value) == RUBY_T_STRING;
1415
+ return FromRubyFundamental<short>::is_convertible(value);
925
1416
  }
926
1417
 
927
- char& convert(VALUE value)
1418
+ short convert(VALUE value)
928
1419
  {
929
1420
  if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
930
1421
  {
931
- return this->arg_->defaultValue<char>();
1422
+ return this->arg_->defaultValue<short>();
932
1423
  }
933
1424
  else
934
1425
  {
935
- this->converted_ = charFromRuby<char>(value);
936
- return this->converted_;
1426
+ return FromRubyFundamental<short>::convert(value);
937
1427
  }
938
1428
  }
939
1429
 
940
1430
  private:
941
1431
  Arg* arg_ = nullptr;
942
- char converted_ = 0;
943
1432
  };
944
1433
 
945
1434
  template<>
946
- class From_Ruby<char*>
1435
+ class From_Ruby<short&>
947
1436
  {
948
1437
  public:
949
- bool is_convertible(VALUE value)
950
- {
951
- return rb_type(value) == RUBY_T_STRING;
952
- }
1438
+ From_Ruby() = default;
953
1439
 
954
- char* convert(VALUE value)
1440
+ explicit From_Ruby(Arg* arg) : arg_(arg)
955
1441
  {
956
- if (value == Qnil)
957
- {
958
- return nullptr;
959
- }
960
- else
961
- {
962
- detail::protect(rb_check_type, value, (int)T_STRING);
963
- return RSTRING_PTR(value);
964
- }
965
1442
  }
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)
1443
+
1444
+ Convertible is_convertible(VALUE value)
974
1445
  {
975
- return rb_type(value) == RUBY_T_STRING;
1446
+ return FromRubyFundamental<short>::is_convertible(value);
976
1447
  }
977
1448
 
978
- char const* convert(VALUE value)
1449
+ short& convert(VALUE value)
979
1450
  {
980
- if (value == Qnil)
1451
+ if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
981
1452
  {
982
- return nullptr;
1453
+ return this->arg_->defaultValue<short>();
983
1454
  }
984
1455
  else
985
1456
  {
986
- detail::protect(rb_check_type, value, (int)T_STRING);
987
- return RSTRING_PTR(value);
1457
+ this->converted_ = FromRubyFundamental<short>::convert(value);
1458
+ return this->converted_;
988
1459
  }
989
1460
  }
1461
+
1462
+ private:
1463
+ Arg* arg_ = nullptr;
1464
+ short converted_ = 0;
990
1465
  };
991
1466
 
992
- // =========== unsinged char ============
993
1467
  template<>
994
- class From_Ruby<unsigned char>
1468
+ class From_Ruby<short*>
995
1469
  {
996
1470
  public:
997
1471
  From_Ruby() = default;
@@ -1000,62 +1474,37 @@ namespace Rice::detail
1000
1474
  {
1001
1475
  }
1002
1476
 
1003
- bool is_convertible(VALUE value)
1004
- {
1005
- return rb_type(value) == RUBY_T_STRING;
1006
- }
1477
+ // Need move constructor and assignment due to std::unique_ptr
1478
+ From_Ruby(From_Ruby&& other) = default;
1479
+ From_Ruby& operator=(From_Ruby&& other) = default;
1007
1480
 
1008
- unsigned char convert(VALUE value)
1481
+ ~From_Ruby()
1009
1482
  {
1010
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1483
+ if (this->arg_ && this->arg_->isOwner())
1011
1484
  {
1012
- return this->arg_->defaultValue<unsigned char>();
1013
- }
1014
- else
1015
- {
1016
- return charFromRuby<unsigned char>(value);
1485
+ this->converted_.release();
1017
1486
  }
1018
1487
  }
1019
-
1020
- private:
1021
- Arg* arg_ = nullptr;
1022
- };
1023
1488
 
1024
- // =========== signed char ============
1025
- template<>
1026
- class From_Ruby<signed char>
1027
- {
1028
- public:
1029
- From_Ruby() = default;
1030
-
1031
- explicit From_Ruby(Arg* arg) : arg_(arg)
1489
+ Convertible is_convertible(VALUE value)
1032
1490
  {
1491
+ return FromRubyFundamental<short*>::is_convertible(value);
1033
1492
  }
1034
1493
 
1035
- bool is_convertible(VALUE value)
1494
+ short* convert(VALUE value)
1036
1495
  {
1037
- return rb_type(value) == RUBY_T_STRING;
1496
+ this->converted_ = FromRubyFundamental<short*>::convert(value);
1497
+ return this->converted_.get();
1038
1498
  }
1039
1499
 
1040
- signed char convert(VALUE value)
1041
- {
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
- }
1050
- }
1051
-
1052
1500
  private:
1053
1501
  Arg* arg_ = nullptr;
1502
+ std::unique_ptr<short[]> converted_;
1054
1503
  };
1055
1504
 
1056
- // =========== double ============
1505
+ // =========== unsigned short ============
1057
1506
  template<>
1058
- class From_Ruby<double>
1507
+ class From_Ruby<unsigned short>
1059
1508
  {
1060
1509
  public:
1061
1510
  From_Ruby() = default;
@@ -1064,20 +1513,20 @@ namespace Rice::detail
1064
1513
  {
1065
1514
  }
1066
1515
 
1067
- bool is_convertible(VALUE value)
1516
+ Convertible is_convertible(VALUE value)
1068
1517
  {
1069
- return rb_type(value) == RUBY_T_FLOAT;
1518
+ return FromRubyFundamental<unsigned short>::is_convertible(value);
1070
1519
  }
1071
1520
 
1072
- double convert(VALUE value)
1521
+ unsigned short convert(VALUE value)
1073
1522
  {
1074
1523
  if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1075
1524
  {
1076
- return this->arg_->defaultValue<double>();
1525
+ return this->arg_->defaultValue<unsigned short>();
1077
1526
  }
1078
1527
  else
1079
1528
  {
1080
- return protect(rb_num2dbl, value);
1529
+ return FromRubyFundamental<unsigned short>::convert(value);
1081
1530
  }
1082
1531
  }
1083
1532
 
@@ -1086,7 +1535,7 @@ namespace Rice::detail
1086
1535
  };
1087
1536
 
1088
1537
  template<>
1089
- class From_Ruby<double&>
1538
+ class From_Ruby<unsigned short&>
1090
1539
  {
1091
1540
  public:
1092
1541
  From_Ruby() = default;
@@ -1095,144 +1544,152 @@ namespace Rice::detail
1095
1544
  {
1096
1545
  }
1097
1546
 
1098
- bool is_convertible(VALUE value)
1547
+ Convertible is_convertible(VALUE value)
1099
1548
  {
1100
- return rb_type(value) == RUBY_T_FLOAT;
1549
+ return FromRubyFundamental<unsigned short>::is_convertible(value);
1101
1550
  }
1102
1551
 
1103
- double& convert(VALUE value)
1552
+ unsigned short& convert(VALUE value)
1104
1553
  {
1105
1554
  if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1106
1555
  {
1107
- return this->arg_->defaultValue<double>();
1556
+ return this->arg_->defaultValue<unsigned short>();
1108
1557
  }
1109
1558
  else
1110
1559
  {
1111
- this->converted_ = protect(rb_num2dbl, value);
1560
+ this->converted_ = FromRubyFundamental<unsigned short>::convert(value);
1112
1561
  return this->converted_;
1113
1562
  }
1114
1563
  }
1115
1564
 
1116
1565
  private:
1117
1566
  Arg* arg_ = nullptr;
1118
- double converted_;
1567
+ unsigned short converted_ = 0;
1119
1568
  };
1120
1569
 
1121
1570
  template<>
1122
- class From_Ruby<double*>
1571
+ class From_Ruby<unsigned short*>
1123
1572
  {
1124
1573
  public:
1125
- bool is_convertible(VALUE value)
1574
+ From_Ruby() = default;
1575
+
1576
+ explicit From_Ruby(Arg* arg) : arg_(arg)
1126
1577
  {
1127
- return rb_type(value) == RUBY_T_FLOAT;
1128
1578
  }
1129
1579
 
1130
- double* convert(VALUE value)
1580
+ // Need move constructor and assignment due to std::unique_ptr
1581
+ From_Ruby(From_Ruby&& other) = default;
1582
+ From_Ruby& operator=(From_Ruby&& other) = default;
1583
+
1584
+ ~From_Ruby()
1131
1585
  {
1132
- if (value == Qnil)
1133
- {
1134
- return nullptr;
1135
- }
1136
- else
1586
+ if (this->arg_ && this->arg_->isOwner())
1137
1587
  {
1138
- this->converted_ = protect(rb_num2dbl, value);
1139
- return &this->converted_;
1588
+ this->converted_.release();
1140
1589
  }
1141
1590
  }
1142
1591
 
1143
- private:
1144
- double converted_;
1145
- };
1146
-
1147
- // =========== float ============
1148
- template<>
1149
- class From_Ruby<float>
1150
- {
1151
- public:
1152
- From_Ruby() = default;
1153
-
1154
- explicit From_Ruby(Arg* arg) : arg_(arg)
1592
+ Convertible is_convertible(VALUE value)
1155
1593
  {
1594
+ return FromRubyFundamental<unsigned short*>::is_convertible(value);
1156
1595
  }
1157
1596
 
1158
- bool is_convertible(VALUE value)
1597
+ unsigned short* convert(VALUE value)
1159
1598
  {
1160
- return rb_type(value) == RUBY_T_FLOAT;
1599
+ this->converted_ = FromRubyFundamental<unsigned short*>::convert(value);
1600
+ return this->converted_.get();
1161
1601
  }
1162
1602
 
1163
- float convert(VALUE value)
1164
- {
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
- }
1173
- }
1174
-
1175
1603
  private:
1176
1604
  Arg* arg_ = nullptr;
1605
+ std::unique_ptr<unsigned short[]> converted_;
1177
1606
  };
1178
1607
 
1179
1608
  template<>
1180
- class From_Ruby<float&>
1609
+ class From_Ruby<void*>
1181
1610
  {
1182
1611
  public:
1183
1612
  From_Ruby() = default;
1184
1613
 
1185
1614
  explicit From_Ruby(Arg* arg) : arg_(arg)
1186
1615
  {
1616
+ if (this->arg_->isOwner())
1617
+ {
1618
+ throw Exception(rb_eTypeError, "Cannot transfer ownership of string data to C++ void pointer");
1619
+ }
1187
1620
  }
1188
1621
 
1189
- bool is_convertible(VALUE value)
1190
- {
1191
- return rb_type(value) == RUBY_T_FLOAT;
1192
- }
1193
-
1194
- float& convert(VALUE value)
1622
+ Convertible is_convertible(VALUE value)
1195
1623
  {
1196
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1624
+ if (this->arg_ && this->arg_->isOpaque())
1197
1625
  {
1198
- return this->arg_->defaultValue<float>();
1626
+ return Convertible::Exact;
1199
1627
  }
1200
- else
1628
+
1629
+ switch (rb_type(value))
1201
1630
  {
1202
- this->converted_ = (float)protect(rb_num2dbl, value);
1203
- return this->converted_;
1631
+ case RUBY_T_DATA:
1632
+ {
1633
+ return Convertible::Exact;
1634
+ break;
1635
+ }
1636
+ case RUBY_T_STRING:
1637
+ {
1638
+ if (RB_ENCODING_IS_ASCII8BIT(value))
1639
+ return Convertible::Exact;
1640
+ else
1641
+ return Convertible::None;
1642
+ break;
1643
+ }
1644
+ case RUBY_T_NIL:
1645
+ {
1646
+ return Convertible::Exact;
1647
+ break;
1648
+ }
1649
+ default:
1650
+ {
1651
+ return Convertible::None;
1652
+ }
1204
1653
  }
1205
1654
  }
1206
1655
 
1207
- private:
1208
- Arg* arg_ = nullptr;
1209
- float converted_;
1210
- };
1211
-
1212
- template<>
1213
- class From_Ruby<float*>
1214
- {
1215
- public:
1216
- bool is_convertible(VALUE value)
1217
- {
1218
- return rb_type(value) == RUBY_T_FLOAT;
1219
- }
1220
-
1221
- float* convert(VALUE value)
1656
+ void* convert(VALUE value)
1222
1657
  {
1223
- if (value == Qnil)
1658
+ if (this->arg_ && this->arg_->isOpaque())
1224
1659
  {
1225
- return nullptr;
1660
+ return (void*)value;
1226
1661
  }
1227
- else
1662
+
1663
+ switch (rb_type(value))
1228
1664
  {
1229
- this->converted_ = (float)protect(rb_num2dbl, value);
1230
- return &this->converted_;
1665
+ case RUBY_T_DATA:
1666
+ {
1667
+ // Since C++ is not telling us type information, we need to extract it
1668
+ // from the Ruby object.
1669
+ const rb_data_type_t* rb_type = RTYPEDDATA_TYPE(value);
1670
+ return detail::unwrap<void>(value, (rb_data_type_t*)rb_type, this->arg_ && this->arg_->isOwner());
1671
+ break;
1672
+ }
1673
+ case RUBY_T_STRING:
1674
+ {
1675
+ // String must be formatted in a way the receiver understands! This likely means it was created
1676
+ // by Array.pack. Once the underlying string goes away the passed in data becomes invalid!
1677
+ return (void*)RSTRING_PTR(value);
1678
+ break;
1679
+ }
1680
+ case RUBY_T_NIL:
1681
+ {
1682
+ return nullptr;
1683
+ break;
1684
+ }
1685
+ default:
1686
+ {
1687
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
1688
+ detail::protect(rb_obj_classname, value), "pointer");
1689
+ }
1231
1690
  }
1232
1691
  }
1233
-
1234
1692
  private:
1235
- float converted_;
1693
+ Arg* arg_ = nullptr;
1236
1694
  };
1237
- }
1238
- #endif // Rice__detail__from_ruby__ipp_
1695
+ }