rice 4.3.3 → 4.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +63 -26
  3. data/README.md +7 -2
  4. data/Rakefile +7 -1
  5. data/include/rice/rice.hpp +7291 -4430
  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 -15
  52. data/rice/detail/NativeRegistry.ipp +23 -48
  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
+ }