rice 4.6.1 → 4.7.1

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 (187) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +38 -0
  3. data/CMakeLists.txt +0 -4
  4. data/Rakefile +2 -8
  5. data/bin/rice-doc.rb +211 -0
  6. data/bin/rice-rbs.rb +92 -0
  7. data/include/rice/rice.hpp +4694 -3704
  8. data/include/rice/stl.hpp +840 -294
  9. data/lib/rice/doc/cpp_reference.rb +166 -0
  10. data/lib/rice/doc/doxygen.rb +294 -0
  11. data/lib/rice/doc/mkdocs.rb +298 -0
  12. data/lib/rice/doc/rice.rb +29 -0
  13. data/lib/rice/doc/ruby.rb +37 -0
  14. data/lib/rice/doc.rb +5 -0
  15. data/lib/{make_rice_headers.rb → rice/make_rice_headers.rb} +3 -0
  16. data/lib/rice/native.rb +18 -0
  17. data/lib/rice/native_registry.rb +21 -0
  18. data/lib/rice/parameter.rb +7 -0
  19. data/lib/rice/rbs.rb +104 -0
  20. data/lib/rice/version.rb +1 -1
  21. data/lib/rice.rb +4 -0
  22. data/lib/rubygems/cmake_builder.rb +24 -27
  23. data/rice/Arg.hpp +4 -4
  24. data/rice/Arg.ipp +4 -4
  25. data/rice/Buffer.hpp +32 -28
  26. data/rice/Buffer.ipp +306 -178
  27. data/rice/Data_Object.ipp +136 -88
  28. data/rice/Data_Type.hpp +5 -7
  29. data/rice/Data_Type.ipp +48 -29
  30. data/rice/Enum.ipp +15 -21
  31. data/rice/Function.hpp +17 -0
  32. data/rice/Function.ipp +13 -0
  33. data/rice/Pointer.hpp +15 -0
  34. data/rice/Pointer.ipp +49 -0
  35. data/rice/Return.hpp +1 -1
  36. data/rice/Return.ipp +2 -2
  37. data/rice/api.hpp +30 -0
  38. data/rice/cpp_api/Array.hpp +4 -4
  39. data/rice/cpp_api/Array.ipp +50 -5
  40. data/rice/cpp_api/Class.hpp +0 -5
  41. data/rice/cpp_api/Class.ipp +19 -0
  42. data/rice/cpp_api/Hash.ipp +20 -0
  43. data/rice/cpp_api/Module.hpp +6 -3
  44. data/rice/cpp_api/Module.ipp +49 -11
  45. data/rice/cpp_api/Object.ipp +31 -2
  46. data/rice/cpp_api/String.hpp +1 -2
  47. data/rice/cpp_api/String.ipp +21 -1
  48. data/rice/cpp_api/Struct.ipp +5 -0
  49. data/rice/cpp_api/Symbol.ipp +43 -0
  50. data/rice/cpp_api/shared_methods.hpp +12 -12
  51. data/rice/detail/MethodInfo.hpp +4 -2
  52. data/rice/detail/MethodInfo.ipp +19 -3
  53. data/rice/detail/ModuleRegistry.hpp +18 -0
  54. data/rice/detail/ModuleRegistry.ipp +25 -0
  55. data/rice/detail/Native.hpp +45 -2
  56. data/rice/detail/Native.ipp +196 -6
  57. data/rice/detail/NativeAttributeGet.hpp +9 -4
  58. data/rice/detail/NativeAttributeGet.ipp +65 -11
  59. data/rice/detail/NativeAttributeSet.hpp +4 -0
  60. data/rice/detail/NativeAttributeSet.ipp +30 -2
  61. data/rice/detail/NativeCallbackFFI.ipp +2 -2
  62. data/rice/detail/NativeCallbackSimple.ipp +1 -1
  63. data/rice/detail/NativeFunction.hpp +11 -49
  64. data/rice/detail/NativeFunction.ipp +82 -379
  65. data/rice/detail/NativeInvoker.hpp +74 -0
  66. data/rice/detail/NativeInvoker.ipp +197 -0
  67. data/rice/detail/NativeIterator.hpp +4 -0
  68. data/rice/detail/NativeIterator.ipp +19 -0
  69. data/rice/detail/NativeMethod.hpp +97 -0
  70. data/rice/detail/NativeMethod.ipp +332 -0
  71. data/rice/detail/NativeProc.hpp +51 -0
  72. data/rice/detail/NativeProc.ipp +133 -0
  73. data/rice/detail/NativeRegistry.hpp +8 -0
  74. data/rice/detail/NativeRegistry.ipp +26 -0
  75. data/rice/detail/Parameter.hpp +47 -0
  76. data/rice/detail/Parameter.ipp +105 -0
  77. data/rice/detail/Proc.ipp +14 -13
  78. data/rice/detail/Registries.hpp +1 -0
  79. data/rice/detail/RubyType.hpp +0 -2
  80. data/rice/detail/RubyType.ipp +15 -33
  81. data/rice/detail/Type.hpp +44 -8
  82. data/rice/detail/Type.ipp +151 -49
  83. data/rice/detail/TypeRegistry.hpp +3 -0
  84. data/rice/detail/TypeRegistry.ipp +17 -27
  85. data/rice/detail/Types.ipp +430 -0
  86. data/rice/detail/Wrapper.hpp +12 -0
  87. data/rice/detail/Wrapper.ipp +45 -2
  88. data/rice/detail/from_ruby.ipp +567 -1073
  89. data/rice/detail/ruby.hpp +1 -0
  90. data/rice/detail/to_ruby.ipp +4 -635
  91. data/rice/libc/file.ipp +3 -6
  92. data/rice/rice.hpp +22 -12
  93. data/rice/rice_api/Arg.hpp +7 -0
  94. data/rice/rice_api/Arg.ipp +9 -0
  95. data/rice/rice_api/ModuleRegistry.hpp +7 -0
  96. data/rice/rice_api/ModuleRegistry.ipp +10 -0
  97. data/rice/rice_api/Native.hpp +7 -0
  98. data/rice/rice_api/Native.ipp +52 -0
  99. data/rice/rice_api/NativeRegistry.hpp +7 -0
  100. data/rice/rice_api/NativeRegistry.ipp +21 -0
  101. data/rice/rice_api/Parameter.hpp +7 -0
  102. data/rice/rice_api/Parameter.ipp +11 -0
  103. data/rice/rice_api/Registries.hpp +6 -0
  104. data/rice/rice_api/Registries.ipp +12 -0
  105. data/rice/rice_api/TypeRegistry.hpp +7 -0
  106. data/rice/rice_api/TypeRegistry.ipp +10 -0
  107. data/rice/stl/complex.ipp +35 -0
  108. data/rice/stl/exception.ipp +20 -7
  109. data/rice/stl/filesystem.hpp +6 -0
  110. data/rice/stl/filesystem.ipp +34 -0
  111. data/rice/stl/map.ipp +13 -21
  112. data/rice/stl/monostate.ipp +37 -1
  113. data/rice/stl/multimap.ipp +17 -24
  114. data/rice/stl/optional.ipp +47 -2
  115. data/rice/stl/pair.ipp +23 -58
  116. data/rice/stl/reference_wrapper.ipp +22 -1
  117. data/rice/stl/set.ipp +17 -9
  118. data/rice/stl/shared_ptr.ipp +44 -17
  119. data/rice/stl/string.ipp +175 -7
  120. data/rice/stl/string_view.ipp +23 -0
  121. data/rice/stl/tuple.ipp +38 -9
  122. data/rice/stl/unique_ptr.ipp +46 -2
  123. data/rice/stl/unordered_map.ipp +13 -21
  124. data/rice/stl/variant.ipp +47 -11
  125. data/rice/stl/vector.ipp +183 -104
  126. data/rice/stl.hpp +1 -0
  127. data/rice/traits/function_traits.hpp +2 -2
  128. data/rice/traits/method_traits.hpp +5 -16
  129. data/rice/traits/rice_traits.hpp +24 -4
  130. data/rice.gemspec +10 -22
  131. data/test/embed_ruby.cpp +0 -3
  132. data/test/test_Array.cpp +38 -38
  133. data/test/test_Attribute.cpp +187 -2
  134. data/test/test_Buffer.cpp +302 -26
  135. data/test/test_Callback.cpp +2 -3
  136. data/test/test_Class.cpp +5 -5
  137. data/test/test_Data_Object.cpp +1 -56
  138. data/test/test_Data_Type.cpp +20 -30
  139. data/test/test_Enum.cpp +4 -46
  140. data/test/test_From_Ruby.cpp +89 -82
  141. data/test/test_GVL.cpp +109 -0
  142. data/test/test_Iterator.cpp +1 -1
  143. data/test/test_Keep_Alive_No_Wrapper.cpp +5 -3
  144. data/test/test_Module.cpp +8 -9
  145. data/test/test_Object.cpp +1 -1
  146. data/test/test_Overloads.cpp +58 -10
  147. data/test/test_Stl_Map.cpp +8 -8
  148. data/test/test_Stl_Multimap.cpp +4 -4
  149. data/test/test_Stl_Pair.cpp +5 -3
  150. data/test/test_Stl_SharedPtr.cpp +24 -12
  151. data/test/test_Stl_String_View.cpp +10 -0
  152. data/test/test_Stl_Tuple.cpp +1 -1
  153. data/test/test_Stl_UniquePtr.cpp +8 -0
  154. data/test/test_Stl_Unordered_Map.cpp +9 -9
  155. data/test/test_Stl_Variant.cpp +9 -3
  156. data/test/test_Stl_Vector.cpp +118 -13
  157. data/test/test_Symbol.cpp +12 -0
  158. data/test/test_To_Ruby.cpp +35 -28
  159. data/test/test_Type.cpp +256 -53
  160. data/test/unittest.hpp +35 -0
  161. metadata +52 -34
  162. data/rice/Init.hpp +0 -8
  163. data/rice/Init.ipp +0 -8
  164. data/rice/detail/RubyFunction.hpp +0 -31
  165. data/rice/detail/RubyFunction.ipp +0 -77
  166. data/sample/callbacks/extconf.rb +0 -5
  167. data/sample/callbacks/sample_callbacks.cpp +0 -35
  168. data/sample/callbacks/test.rb +0 -28
  169. data/sample/enum/extconf.rb +0 -5
  170. data/sample/enum/sample_enum.cpp +0 -40
  171. data/sample/enum/test.rb +0 -8
  172. data/sample/inheritance/animals.cpp +0 -82
  173. data/sample/inheritance/extconf.rb +0 -5
  174. data/sample/inheritance/test.rb +0 -7
  175. data/sample/map/extconf.rb +0 -5
  176. data/sample/map/map.cpp +0 -73
  177. data/sample/map/test.rb +0 -7
  178. data/test/ext/t1/Foo.hpp +0 -10
  179. data/test/ext/t1/extconf.rb +0 -4
  180. data/test/ext/t1/t1.cpp +0 -13
  181. data/test/ext/t2/extconf.rb +0 -4
  182. data/test/ext/t2/t2.cpp +0 -11
  183. data/test/ruby/test_callbacks_sample.rb +0 -28
  184. data/test/ruby/test_multiple_extensions.rb +0 -18
  185. data/test/ruby/test_multiple_extensions_same_class.rb +0 -14
  186. data/test/ruby/test_multiple_extensions_with_inheritance.rb +0 -20
  187. /data/test/{test_Stl_Type.cpp → test_Stl_Type_Info.cpp} +0 -0
data/include/rice/stl.hpp CHANGED
@@ -17,14 +17,17 @@ namespace Rice::stl
17
17
  // so define it for Ruby if necessary
18
18
  namespace Rice::stl
19
19
  {
20
- inline Class rb_cStlException;
21
-
22
- inline void define_stl_exception()
20
+ inline void define_stl_exceptions()
23
21
  {
24
22
  Module rb_mStd = define_module("Std");
25
- rb_cStlException = define_class_under<std::exception>(rb_mStd, "Exception", rb_eStandardError).
26
- define_constructor(Constructor<std::exception>()).
27
- define_method("message", &std::exception::what);
23
+
24
+ define_class_under<std::exception>(rb_mStd, "Exception", rb_eStandardError).
25
+ define_constructor(Constructor<std::exception>()).
26
+ define_method("message", &std::exception::what);
27
+
28
+ define_class_under<std::runtime_error>(rb_mStd, "RuntimeError", rb_eRuntimeError).
29
+ define_constructor(Constructor<std::runtime_error, const char*>()).
30
+ define_method("message", &std::runtime_error::what);
28
31
  }
29
32
  }
30
33
 
@@ -35,7 +38,17 @@ namespace Rice::detail
35
38
  {
36
39
  static bool verify()
37
40
  {
38
- Rice::stl::define_stl_exception();
41
+ Rice::stl::define_stl_exceptions();
42
+ return true;
43
+ }
44
+ };
45
+
46
+ template<>
47
+ struct Type<std::runtime_error>
48
+ {
49
+ static bool verify()
50
+ {
51
+ Rice::stl::define_stl_exceptions();
39
52
  return true;
40
53
  }
41
54
  };
@@ -90,59 +103,186 @@ namespace Rice::detail
90
103
  {
91
104
  return true;
92
105
  }
106
+
107
+ static VALUE rubyKlass()
108
+ {
109
+ return rb_cString;
110
+ }
111
+ };
112
+
113
+ template<int N>
114
+ struct Type<std::string[N]>
115
+ {
116
+ static bool verify()
117
+ {
118
+ return true;
119
+ }
120
+
121
+ static VALUE rubyKlass()
122
+ {
123
+ return rb_cString;
124
+ }
125
+ };
126
+
127
+ template<>
128
+ struct Type<std::string*>
129
+ {
130
+ static bool verify()
131
+ {
132
+ return true;
133
+ }
134
+
135
+ static VALUE rubyKlass()
136
+ {
137
+ using Pointer_T = Pointer<std::string>;
138
+ std::pair<VALUE, rb_data_type_t*> pair = Registries::instance.types.getType<Pointer_T>();
139
+ return pair.first;
140
+ }
141
+ };
142
+
143
+ template<>
144
+ struct Type<std::string**>
145
+ {
146
+ static bool verify()
147
+ {
148
+ return true;
149
+ }
150
+
151
+ static VALUE rubyKlass()
152
+ {
153
+ using Pointer_T = Pointer<std::string*>;
154
+ std::pair<VALUE, rb_data_type_t*> pair = Registries::instance.types.getType<Pointer_T>();
155
+ return pair.first;
156
+ }
93
157
  };
94
158
 
95
159
  template<>
96
160
  class To_Ruby<std::string>
97
161
  {
98
162
  public:
163
+ To_Ruby() = default;
164
+
165
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
166
+ {
167
+ }
168
+
99
169
  VALUE convert(const std::string& x)
100
170
  {
101
171
  return detail::protect(rb_external_str_new, x.data(), (long)x.size());
102
172
  }
173
+
174
+ private:
175
+ Return* returnInfo_ = nullptr;
103
176
  };
104
177
 
105
178
  template<>
106
179
  class To_Ruby<std::string&>
107
180
  {
108
181
  public:
182
+ To_Ruby() = default;
183
+
184
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
185
+ {
186
+ }
187
+
109
188
  VALUE convert(const std::string& x)
110
189
  {
111
190
  return detail::protect(rb_external_str_new, x.data(), (long)x.size());
112
191
  }
192
+
193
+ private:
194
+ Return* returnInfo_ = nullptr;
195
+ };
196
+
197
+ template<int N>
198
+ class To_Ruby<std::string[N]>
199
+ {
200
+ public:
201
+ To_Ruby() = default;
202
+
203
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
204
+ {
205
+ }
206
+
207
+ VALUE convert(std::string data[N])
208
+ {
209
+ Buffer<std::string> buffer(data, N);
210
+ Data_Object<Buffer<std::string>> dataObject(std::move(buffer));
211
+ return dataObject.value();
212
+ }
213
+ private:
214
+ Return* returnInfo_ = nullptr;
113
215
  };
114
216
 
115
217
  template<>
116
218
  class To_Ruby<std::string*>
117
219
  {
118
220
  public:
119
- VALUE convert(const std::string* x)
221
+ To_Ruby() = default;
222
+
223
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
120
224
  {
121
- return detail::protect(rb_external_str_new, x->data(), (long)x->size());
122
225
  }
226
+
227
+ VALUE convert(const std::string* value)
228
+ {
229
+ bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
230
+ bool isBuffer = this->returnInfo_ && this->returnInfo_->isBuffer();
231
+
232
+ if (isBuffer)
233
+ {
234
+ using Pointer_T = Pointer<std::string>;
235
+ return detail::wrap(Data_Type<Pointer_T>::klass(), Data_Type<Pointer_T>::ruby_data_type(), value, isOwner);
236
+ }
237
+ else
238
+ {
239
+ return detail::protect(rb_external_str_new, value->data(), (long)value->size());
240
+ }
241
+ }
242
+
243
+ private:
244
+ Return* returnInfo_ = nullptr;
123
245
  };
124
246
 
125
247
  template<>
126
248
  class To_Ruby<std::string*&>
127
249
  {
128
250
  public:
251
+ To_Ruby() = default;
252
+
253
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
254
+ {
255
+ }
256
+
129
257
  VALUE convert(const std::string* x)
130
258
  {
131
259
  return detail::protect(rb_external_str_new, x->data(), (long)x->size());
132
260
  }
261
+
262
+ private:
263
+ Return* returnInfo_ = nullptr;
133
264
  };
134
265
 
135
- template<>
266
+ /*template<>
136
267
  class To_Ruby<std::string**>
137
268
  {
138
269
  public:
270
+ To_Ruby() = default;
271
+
272
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
273
+ {
274
+ }
275
+
139
276
  VALUE convert(std::string** data)
140
277
  {
141
278
  Buffer<std::string*> buffer(data);
142
279
  Data_Object<Buffer<std::string*>> dataObject(std::move(buffer));
143
280
  return dataObject.value();
144
281
  }
145
- };
282
+
283
+ private:
284
+ Return* returnInfo_ = nullptr;
285
+ };*/
146
286
 
147
287
  template<>
148
288
  class From_Ruby<std::string>
@@ -168,7 +308,7 @@ namespace Rice::detail
168
308
 
169
309
  std::string convert(VALUE value)
170
310
  {
171
- detail::protect(rb_check_type, value, (int)T_STRING);
311
+ detail::protect(rb_check_type, value, (int)RUBY_T_STRING);
172
312
  return std::string(RSTRING_PTR(value), RSTRING_LEN(value));
173
313
  }
174
314
 
@@ -200,7 +340,7 @@ namespace Rice::detail
200
340
 
201
341
  std::string& convert(VALUE value)
202
342
  {
203
- detail::protect(rb_check_type, value, (int)T_STRING);
343
+ detail::protect(rb_check_type, value, (int)RUBY_T_STRING);
204
344
  this->converted_ = std::string(RSTRING_PTR(value), RSTRING_LEN(value));
205
345
  return this->converted_;
206
346
  }
@@ -210,10 +350,50 @@ namespace Rice::detail
210
350
  std::string converted_ = "";
211
351
  };
212
352
 
353
+ template<>
354
+ class From_Ruby<std::string&&>
355
+ {
356
+ public:
357
+ From_Ruby() = default;
358
+
359
+ explicit From_Ruby(Arg* arg) : arg_(arg)
360
+ {
361
+ }
362
+
363
+ Convertible is_convertible(VALUE value)
364
+ {
365
+ switch (rb_type(value))
366
+ {
367
+ case RUBY_T_STRING:
368
+ return Convertible::Exact;
369
+ break;
370
+ default:
371
+ return Convertible::None;
372
+ }
373
+ }
374
+
375
+ std::string&& convert(VALUE value)
376
+ {
377
+ detail::protect(rb_check_type, value, (int)T_STRING);
378
+ this->converted_ = std::string(RSTRING_PTR(value), RSTRING_LEN(value));
379
+ return std::move(this->converted_);
380
+ }
381
+
382
+ private:
383
+ Arg* arg_ = nullptr;
384
+ std::string converted_ = "";
385
+ };
386
+
213
387
  template<>
214
388
  class From_Ruby<std::string*>
215
389
  {
216
390
  public:
391
+ From_Ruby() = default;
392
+
393
+ explicit From_Ruby(Arg* arg) : arg_(arg)
394
+ {
395
+ }
396
+
217
397
  Convertible is_convertible(VALUE value)
218
398
  {
219
399
  switch (rb_type(value))
@@ -228,12 +408,13 @@ namespace Rice::detail
228
408
 
229
409
  std::string* convert(VALUE value)
230
410
  {
231
- detail::protect(rb_check_type, value, (int)T_STRING);
411
+ detail::protect(rb_check_type, value, (int)RUBY_T_STRING);
232
412
  this->converted_ = std::string(RSTRING_PTR(value), RSTRING_LEN(value));
233
413
  return &this->converted_;
234
414
  }
235
415
 
236
416
  private:
417
+ Arg* arg_ = nullptr;
237
418
  std::string converted_;
238
419
  };
239
420
  }
@@ -253,26 +434,49 @@ namespace Rice::detail
253
434
  {
254
435
  return true;
255
436
  }
437
+
438
+ static VALUE rubyKlass()
439
+ {
440
+ return rb_cString;
441
+ }
256
442
  };
257
443
 
258
444
  template<>
259
445
  class To_Ruby<std::string_view>
260
446
  {
261
447
  public:
448
+ To_Ruby() = default;
449
+
450
+ explicit To_Ruby(Arg* arg) : arg_(arg)
451
+ {
452
+ }
453
+
262
454
  VALUE convert(std::string_view const& x)
263
455
  {
264
456
  return detail::protect(rb_external_str_new, x.data(), (long)x.size());
265
457
  }
458
+
459
+ private:
460
+ Arg* arg_ = nullptr;
266
461
  };
267
462
 
268
463
  template<>
269
464
  class To_Ruby<std::string_view&>
270
465
  {
271
466
  public:
467
+ To_Ruby() = default;
468
+
469
+ explicit To_Ruby(Arg* arg) : arg_(arg)
470
+ {
471
+ }
472
+
272
473
  VALUE convert(std::string_view const& x)
273
474
  {
274
475
  return detail::protect(rb_external_str_new, x.data(), (long)x.size());
275
476
  }
477
+
478
+ private:
479
+ Arg* arg_ = nullptr;
276
480
  };
277
481
 
278
482
  template<>
@@ -323,12 +527,23 @@ namespace Rice::detail
323
527
  {
324
528
  return true;
325
529
  }
530
+
531
+ static VALUE rubyKlass()
532
+ {
533
+ return rb_cComplex;
534
+ }
326
535
  };
327
536
 
328
537
  template<typename T>
329
538
  class To_Ruby<std::complex<T>>
330
539
  {
331
540
  public:
541
+ To_Ruby() = default;
542
+
543
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
544
+ {
545
+ }
546
+
332
547
  VALUE convert(const std::complex<T>& data)
333
548
  {
334
549
  std::vector<VALUE> args(2);
@@ -336,12 +551,21 @@ namespace Rice::detail
336
551
  args[1] = To_Ruby<T>().convert(data.imag());
337
552
  return protect(rb_funcallv, rb_mKernel, rb_intern("Complex"), (int)args.size(), (const VALUE*)args.data());
338
553
  }
554
+
555
+ private:
556
+ Return* returnInfo_ = nullptr;
339
557
  };
340
558
 
341
559
  template<typename T>
342
560
  class To_Ruby<std::complex<T>&>
343
561
  {
344
562
  public:
563
+ To_Ruby() = default;
564
+
565
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
566
+ {
567
+ }
568
+
345
569
  VALUE convert(const std::complex<T>& data)
346
570
  {
347
571
  std::vector<VALUE> args(2);
@@ -349,12 +573,21 @@ namespace Rice::detail
349
573
  args[1] = To_Ruby<T>().convert(data.imag());
350
574
  return protect(rb_funcallv, rb_mKernel, rb_intern("Complex"), (int)args.size(), (const VALUE*)args.data());
351
575
  }
576
+
577
+ private:
578
+ Return* returnInfo_ = nullptr;
352
579
  };
353
580
 
354
581
  template<typename T>
355
582
  class From_Ruby<std::complex<T>>
356
583
  {
357
584
  public:
585
+ From_Ruby() = default;
586
+
587
+ explicit From_Ruby(Arg* arg)
588
+ {
589
+ }
590
+
358
591
  Convertible is_convertible(VALUE value)
359
592
  {
360
593
  switch (rb_type(value))
@@ -380,6 +613,12 @@ namespace Rice::detail
380
613
  class From_Ruby<std::complex<T>&>
381
614
  {
382
615
  public:
616
+ From_Ruby() = default;
617
+
618
+ explicit From_Ruby(Arg* arg)
619
+ {
620
+ }
621
+
383
622
  Convertible is_convertible(VALUE value)
384
623
  {
385
624
  switch (rb_type(value))
@@ -407,6 +646,46 @@ namespace Rice::detail
407
646
  }
408
647
 
409
648
 
649
+ // ========= filesystem.hpp =========
650
+
651
+
652
+ // --------- filesystem.ipp ---------
653
+ #include <filesystem>
654
+
655
+ namespace Rice
656
+ {
657
+ namespace stl
658
+ {
659
+ inline void define_filesystem_path()
660
+ {
661
+ Module rb_mStd = define_module("Std");
662
+ Module rb_mFileSystem = define_module_under(rb_mStd, "Filesystem");
663
+
664
+ define_class_under<std::filesystem::path>(rb_mFileSystem, "Path").
665
+ define_constructor(Constructor<std::filesystem::path>()).
666
+ define_constructor(Constructor<std::filesystem::path, std::string>());
667
+ }
668
+ }
669
+ }
670
+
671
+ namespace Rice::detail
672
+ {
673
+ template<>
674
+ struct Type<std::filesystem::path>
675
+ {
676
+ static bool verify()
677
+ {
678
+ if (!Data_Type<std::filesystem::path>::is_defined())
679
+ {
680
+ Rice::stl::define_filesystem_path();
681
+ }
682
+
683
+ return true;
684
+ }
685
+ };
686
+ }
687
+
688
+
410
689
  // ========= optional.hpp =========
411
690
 
412
691
 
@@ -422,23 +701,44 @@ namespace Rice::detail
422
701
  {
423
702
  return Type<intrinsic_type<T>>::verify();
424
703
  }
704
+
705
+ static VALUE rubyKlass()
706
+ {
707
+ TypeMapper<T> typeMapper;
708
+ return typeMapper.rubyKlass();
709
+ }
425
710
  };
426
711
 
427
712
  template<>
428
713
  class To_Ruby<std::nullopt_t>
429
714
  {
430
715
  public:
716
+ To_Ruby() = default;
717
+
718
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
719
+ {
720
+ }
721
+
431
722
  VALUE convert(const std::nullopt_t& _)
432
723
  {
433
724
  return Qnil;
434
725
  }
726
+
727
+ private:
728
+ Return* returnInfo_ = nullptr;
435
729
  };
436
730
 
437
731
  template<typename T>
438
732
  class To_Ruby<std::optional<T>>
439
733
  {
440
734
  public:
441
- static VALUE convert(const std::optional<T>& data, bool takeOwnership = false)
735
+ To_Ruby() = default;
736
+
737
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
738
+ {
739
+ }
740
+
741
+ VALUE convert(std::optional<T>& data)
442
742
  {
443
743
  if (data.has_value())
444
744
  {
@@ -449,13 +749,22 @@ namespace Rice::detail
449
749
  return Qnil;
450
750
  }
451
751
  }
752
+
753
+ private:
754
+ Return* returnInfo_ = nullptr;
452
755
  };
453
756
 
454
757
  template<typename T>
455
758
  class To_Ruby<std::optional<T>&>
456
759
  {
457
760
  public:
458
- static VALUE convert(const std::optional<T>& data, bool takeOwnership = false)
761
+ To_Ruby() = default;
762
+
763
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
764
+ {
765
+ }
766
+
767
+ VALUE convert(const std::optional<T>& data)
459
768
  {
460
769
  if (data.has_value())
461
770
  {
@@ -466,12 +775,21 @@ namespace Rice::detail
466
775
  return Qnil;
467
776
  }
468
777
  }
778
+
779
+ private:
780
+ Return* returnInfo_ = nullptr;
469
781
  };
470
782
 
471
783
  template<typename T>
472
784
  class From_Ruby<std::optional<T>>
473
785
  {
474
786
  public:
787
+ From_Ruby() = default;
788
+
789
+ explicit From_Ruby(Arg* arg)
790
+ {
791
+ }
792
+
475
793
  Convertible is_convertible(VALUE value)
476
794
  {
477
795
  switch (rb_type(value))
@@ -501,6 +819,12 @@ namespace Rice::detail
501
819
  class From_Ruby<std::optional<T>&>
502
820
  {
503
821
  public:
822
+ From_Ruby() = default;
823
+
824
+ explicit From_Ruby(Arg* arg)
825
+ {
826
+ }
827
+
504
828
  Convertible is_convertible(VALUE value)
505
829
  {
506
830
  switch (rb_type(value))
@@ -546,22 +870,43 @@ namespace Rice::detail
546
870
  {
547
871
  return Type<T>::verify();
548
872
  }
873
+
874
+ static VALUE rubyKlass()
875
+ {
876
+ TypeMapper<T> typeMapper;
877
+ return typeMapper.rubyKlass();
878
+ }
549
879
  };
550
880
 
551
881
  template<typename T>
552
882
  class To_Ruby<std::reference_wrapper<T>>
553
883
  {
554
884
  public:
555
- VALUE convert(const std::reference_wrapper<T>& data, bool takeOwnership = false)
885
+ To_Ruby() = default;
886
+
887
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
888
+ {
889
+ }
890
+
891
+ VALUE convert(const std::reference_wrapper<T>& data)
556
892
  {
557
893
  return To_Ruby<T&>().convert(data.get());
558
894
  }
895
+
896
+ private:
897
+ Return* returnInfo_ = nullptr;
559
898
  };
560
899
 
561
900
  template<typename T>
562
901
  class From_Ruby<std::reference_wrapper<T>>
563
902
  {
564
903
  public:
904
+ From_Ruby() = default;
905
+
906
+ explicit From_Ruby(Arg* arg)
907
+ {
908
+ }
909
+
565
910
  Convertible is_convertible(VALUE value)
566
911
  {
567
912
  return this->converter_.is_convertible(value);
@@ -600,78 +945,43 @@ namespace Rice
600
945
  public:
601
946
  PairHelper(Data_Type<T> klass) : klass_(klass)
602
947
  {
603
- this->define_constructor();
604
- this->define_copyable_methods();
605
- this->define_access_methods();
606
- this->define_modify_methods();
948
+ this->define_constructors();
949
+ this->define_attributes();
607
950
  this->define_to_s();
608
951
  }
609
952
 
610
953
  private:
611
- void define_constructor()
954
+ void define_constructors()
612
955
  {
613
- klass_.define_constructor(Constructor<T, typename T::first_type&, typename T::second_type&>());
956
+ klass_.define_constructor(Constructor<T>())
957
+ .define_constructor(Constructor<T, typename T::first_type&, typename T::second_type&>());
958
+
959
+ if constexpr (std::is_copy_constructible_v<typename T::first_type> && std::is_copy_constructible_v<typename T::second_type>)
960
+ {
961
+ klass_.define_constructor(Constructor<T, const T&>());
962
+ }
614
963
  }
615
964
 
616
- void define_copyable_methods()
965
+ void define_attributes()
617
966
  {
618
- if constexpr (std::is_copy_constructible_v<typename T::first_type> && std::is_copy_constructible_v<typename T::second_type>)
967
+ // Access methods
968
+ if constexpr (std::is_const_v<std::remove_reference_t<std::remove_pointer_t<typename T::first_type>>>)
619
969
  {
620
- klass_.define_method("copy", [](T& pair) -> T
621
- {
622
- return pair;
623
- });
970
+ klass_.define_attr("first", &T::first, Rice::AttrAccess::Read);
624
971
  }
625
972
  else
626
973
  {
627
- klass_.define_method("copy", [](T& pair) -> T
628
- {
629
- throw std::runtime_error("Cannot copy pair with non-copy constructible types");
630
- return pair;
631
- });
974
+ klass_.define_attr("first", &T::first, Rice::AttrAccess::ReadWrite);
632
975
  }
633
- }
634
-
635
- void define_access_methods()
636
- {
637
- // Access methods
638
- klass_.define_method("first", [](T& pair) -> typename T::first_type&
639
- {
640
- return pair.first;
641
- })
642
- .define_method("second", [](T& pair) -> typename T::second_type&
643
- {
644
- return pair.second;
645
- });
646
- }
647
976
 
648
- void define_modify_methods()
649
- {
650
- // Access methods
651
- klass_.define_method("first=", [](T& pair, typename T::first_type& value) -> typename T::first_type&
977
+ if constexpr (std::is_const_v<std::remove_reference_t<std::remove_pointer_t<typename T::second_type>>>)
652
978
  {
653
- if constexpr (std::is_const_v<std::remove_reference_t<std::remove_pointer_t<typename T::first_type>>>)
654
- {
655
- throw std::runtime_error("Cannot set pair.first since it is a constant");
656
- }
657
- else
658
- {
659
- pair.first = value;
660
- return pair.first;
661
- }
662
- })
663
- .define_method("second=", [](T& pair, typename T::second_type& value) -> typename T::second_type&
979
+ klass_.define_attr("second", &T::second, Rice::AttrAccess::Read);
980
+ }
981
+ else
664
982
  {
665
- if constexpr (std::is_const_v<std::remove_reference_t<std::remove_pointer_t<typename T::second_type>>>)
666
- {
667
- throw std::runtime_error("Cannot set pair.second since it is a constant");
668
- }
669
- else
670
- {
671
- pair.second = value;
672
- return pair.second;
673
- }
674
- });
983
+ klass_.define_attr("second", &T::second, Rice::AttrAccess::ReadWrite);
984
+ }
675
985
  }
676
986
 
677
987
  void define_to_s()
@@ -707,8 +1017,8 @@ namespace Rice
707
1017
 
708
1018
  if (klassName.empty())
709
1019
  {
710
- std::string typeName = detail::typeName(typeid(Pair_T));
711
- klassName = detail::rubyClassName(typeName);
1020
+ detail::TypeMapper<Pair_T> typeMapper;
1021
+ klassName = typeMapper.rubyName();
712
1022
  }
713
1023
 
714
1024
  Module rb_mStd = define_module("Std");
@@ -777,8 +1087,7 @@ namespace Rice
777
1087
  MapHelper(Data_Type<T> klass) : klass_(klass)
778
1088
  {
779
1089
  this->register_pair();
780
- this->define_constructor();
781
- this->define_copyable_methods();
1090
+ this->define_constructors();
782
1091
  this->define_capacity_methods();
783
1092
  this->define_access_methods();
784
1093
  this->define_comparable_methods();
@@ -795,27 +1104,13 @@ namespace Rice
795
1104
  define_pair<const Key_T, Mapped_T>();
796
1105
  }
797
1106
 
798
- void define_constructor()
1107
+ void define_constructors()
799
1108
  {
800
1109
  klass_.define_constructor(Constructor<T>());
801
- }
802
1110
 
803
- void define_copyable_methods()
804
- {
805
- if constexpr (std::is_copy_constructible_v<Value_T>)
1111
+ if constexpr (std::is_copy_constructible_v<Key_T> && std::is_copy_constructible_v<Value_T>)
806
1112
  {
807
- klass_.define_method("copy", [](T& map) -> T
808
- {
809
- return map;
810
- });
811
- }
812
- else
813
- {
814
- klass_.define_method("copy", [](T& map) -> T
815
- {
816
- throw std::runtime_error("Cannot copy maps with non-copy constructible types");
817
- return map;
818
- });
1113
+ klass_.define_constructor(Constructor<T, const T&>());
819
1114
  }
820
1115
  }
821
1116
 
@@ -998,8 +1293,8 @@ namespace Rice
998
1293
 
999
1294
  if (klassName.empty())
1000
1295
  {
1001
- std::string typeName = detail::typeName(typeid(Map_T));
1002
- klassName = detail::rubyClassName(typeName);
1296
+ detail::TypeMapper<Map_T> typeMapper;
1297
+ klassName = typeMapper.rubyName();
1003
1298
  }
1004
1299
 
1005
1300
  Module rb_mStd = define_module("Std");
@@ -1176,6 +1471,12 @@ namespace Rice
1176
1471
  class From_Ruby<std::map<T, U>*>
1177
1472
  {
1178
1473
  public:
1474
+ From_Ruby() = default;
1475
+
1476
+ explicit From_Ruby(Arg* arg) : arg_(arg)
1477
+ {
1478
+ }
1479
+
1179
1480
  Convertible is_convertible(VALUE value)
1180
1481
  {
1181
1482
  switch (rb_type(value))
@@ -1221,6 +1522,7 @@ namespace Rice
1221
1522
  }
1222
1523
 
1223
1524
  private:
1525
+ Arg* arg_;
1224
1526
  std::map<T, U> converted_;
1225
1527
  };
1226
1528
  }
@@ -1241,32 +1543,62 @@ namespace Rice::detail
1241
1543
  {
1242
1544
  return true;
1243
1545
  }
1546
+
1547
+ static VALUE rubyKlass()
1548
+ {
1549
+ return rb_cNilClass;
1550
+ }
1244
1551
  };
1245
1552
 
1246
1553
  template<>
1247
1554
  class To_Ruby<std::monostate>
1248
1555
  {
1249
1556
  public:
1557
+ To_Ruby() = default;
1558
+
1559
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
1560
+ {
1561
+ }
1562
+
1250
1563
  VALUE convert(const std::monostate& _)
1251
1564
  {
1252
1565
  return Qnil;
1253
1566
  }
1567
+
1568
+
1569
+ private:
1570
+ Return* returnInfo_ = nullptr;
1254
1571
  };
1255
1572
 
1256
1573
  template<>
1257
1574
  class To_Ruby<std::monostate&>
1258
1575
  {
1259
1576
  public:
1260
- static VALUE convert(const std::monostate& data, bool takeOwnership = false)
1577
+ To_Ruby() = default;
1578
+
1579
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
1580
+ {
1581
+ }
1582
+
1583
+ VALUE convert(const std::monostate& data)
1261
1584
  {
1262
1585
  return Qnil;
1263
1586
  }
1587
+
1588
+ private:
1589
+ Return* returnInfo_ = nullptr;
1264
1590
  };
1265
1591
 
1266
1592
  template<>
1267
1593
  class From_Ruby<std::monostate>
1268
1594
  {
1269
1595
  public:
1596
+ From_Ruby() = default;
1597
+
1598
+ explicit From_Ruby(Arg* arg)
1599
+ {
1600
+ }
1601
+
1270
1602
  Convertible is_convertible(VALUE value)
1271
1603
  {
1272
1604
  return value == Qnil ? Convertible::Exact : Convertible::None;
@@ -1289,6 +1621,12 @@ namespace Rice::detail
1289
1621
  class From_Ruby<std::monostate&>
1290
1622
  {
1291
1623
  public:
1624
+ From_Ruby() = default;
1625
+
1626
+ explicit From_Ruby(Arg* arg)
1627
+ {
1628
+ }
1629
+
1292
1630
  Convertible is_convertible(VALUE value)
1293
1631
  {
1294
1632
  return value == Qnil ? Convertible::Exact : Convertible::None;
@@ -1345,8 +1683,7 @@ namespace Rice
1345
1683
  MultimapHelper(Data_Type<T> klass) : klass_(klass)
1346
1684
  {
1347
1685
  this->register_pair();
1348
- this->define_constructor();
1349
- this->define_copyable_methods();
1686
+ this->define_constructors();
1350
1687
  this->define_capacity_methods();
1351
1688
  this->define_access_methods();
1352
1689
  this->define_comparable_methods();
@@ -1362,27 +1699,13 @@ namespace Rice
1362
1699
  define_pair<const Key_T, Mapped_T>();
1363
1700
  }
1364
1701
 
1365
- void define_constructor()
1702
+ void define_constructors()
1366
1703
  {
1367
1704
  klass_.define_constructor(Constructor<T>());
1368
- }
1369
1705
 
1370
- void define_copyable_methods()
1371
- {
1372
- if constexpr (std::is_copy_constructible_v<Value_T>)
1373
- {
1374
- klass_.define_method("copy", [](T& multimap) -> T
1375
- {
1376
- return multimap;
1377
- });
1378
- }
1379
- else
1706
+ if constexpr (std::is_copy_constructible_v<Key_T> && std::is_copy_constructible_v<Value_T>)
1380
1707
  {
1381
- klass_.define_method("copy", [](T& multimap) -> T
1382
- {
1383
- throw std::runtime_error("Cannot copy multimaps with non-copy constructible types");
1384
- return multimap;
1385
- });
1708
+ klass_.define_constructor(Constructor<T, const T&>());
1386
1709
  }
1387
1710
  }
1388
1711
 
@@ -1400,14 +1723,14 @@ namespace Rice
1400
1723
  {
1401
1724
  // Access methods
1402
1725
  klass_.
1403
- define_method("[]", [](const T& multimap, const Key_T& key) -> Array
1726
+ define_method("[]", [](T& multimap, const Key_T& key) -> Array
1404
1727
  {
1405
1728
  Array result;
1406
1729
  auto range = multimap.equal_range(key);
1407
1730
 
1408
1731
  for (auto iter = range.first; iter != range.second; iter++)
1409
1732
  {
1410
- result.push<Mapped_T>(iter->second);
1733
+ result.push(iter->second, false);
1411
1734
  }
1412
1735
 
1413
1736
  return result;
@@ -1510,7 +1833,8 @@ namespace Rice
1510
1833
  auto iter = multimap.begin();
1511
1834
 
1512
1835
  std::stringstream stream;
1513
- stream << "<" << detail::rubyClassName(detail::typeName(typeid(T))) << ":";
1836
+ detail::TypeMapper<T> typeMapper;
1837
+ stream << "<" << typeMapper.rubyName() << ":";
1514
1838
  stream << "{";
1515
1839
 
1516
1840
  for (; iter != multimap.end(); iter++)
@@ -1548,8 +1872,8 @@ namespace Rice
1548
1872
 
1549
1873
  if (klassName.empty())
1550
1874
  {
1551
- std::string typeName = detail::typeName(typeid(MultiMap_T));
1552
- klassName = detail::rubyClassName(typeName);
1875
+ detail::TypeMapper<MultiMap_T> typeMapper;
1876
+ klassName = typeMapper.rubyName();
1553
1877
  }
1554
1878
 
1555
1879
  Module rb_mStd = define_module("Std");
@@ -1723,6 +2047,12 @@ namespace Rice
1723
2047
  class From_Ruby<std::multimap<T, U>*>
1724
2048
  {
1725
2049
  public:
2050
+ From_Ruby() = default;
2051
+
2052
+ explicit From_Ruby(Arg* arg) : arg_(arg)
2053
+ {
2054
+ }
2055
+
1726
2056
  Convertible is_convertible(VALUE value)
1727
2057
  {
1728
2058
  switch (rb_type(value))
@@ -1768,6 +2098,7 @@ namespace Rice
1768
2098
  }
1769
2099
 
1770
2100
  private:
2101
+ Arg* arg_;
1771
2102
  std::multimap<T, U> converted_;
1772
2103
  };
1773
2104
  }
@@ -1961,9 +2292,9 @@ namespace Rice
1961
2292
  klass_.define_method("to_a", [](T& self) -> VALUE
1962
2293
  {
1963
2294
  Array array;
1964
- for (const Value_T& element: self)
2295
+ for (auto element: self)
1965
2296
  {
1966
- array.push(element);
2297
+ array.push(element, false);
1967
2298
  }
1968
2299
 
1969
2300
  return array.value();
@@ -1980,7 +2311,8 @@ namespace Rice
1980
2311
  auto finish = self.end();
1981
2312
 
1982
2313
  std::stringstream stream;
1983
- stream << "<" << detail::rubyClassName(detail::typeName(typeid(T))) << ":";
2314
+ detail::TypeMapper<T> typeMapper;
2315
+ stream << "<" << typeMapper.rubyName() << ":";
1984
2316
  stream << "{";
1985
2317
 
1986
2318
  for (; iter != finish; iter++)
@@ -2021,8 +2353,8 @@ namespace Rice
2021
2353
 
2022
2354
  if (klassName.empty())
2023
2355
  {
2024
- std::string typeName = detail::typeName(typeid(Set_T));
2025
- klassName = detail::rubyClassName(typeName);
2356
+ detail::TypeMapper<Set_T> typeMapper;
2357
+ klassName = typeMapper.rubyName();
2026
2358
  }
2027
2359
 
2028
2360
  Module rb_mStd = define_module("Std");
@@ -2053,11 +2385,11 @@ namespace Rice
2053
2385
  return Qnil;
2054
2386
  };
2055
2387
 
2056
- using NativeFunction_T = NativeFunction<void, decltype(block), false>;
2388
+ using Proc_T = decltype(block);
2389
+ using NativeProc_T = NativeProc<Proc_T>;
2390
+ std::unique_ptr<NativeProc_T> proc(NativeProc_T::define(std::forward<Proc_T>(block)));
2057
2391
 
2058
- // It is ok to use the address of native because it will remain valid while we iterate the set
2059
- NativeFunction_T native(block);
2060
- detail::protect<Function_T>(rb_block_call, rubySet, identifier.id(), 0, nullptr, NativeFunction_T::procEntry, (VALUE)&native);
2392
+ detail::protect<Function_T>(rb_block_call, rubySet, identifier.id(), 0, nullptr, NativeProc_T::resolve, (VALUE)proc.get());
2061
2393
 
2062
2394
  return result;
2063
2395
  }
@@ -2218,6 +2550,12 @@ namespace Rice
2218
2550
  private:
2219
2551
  static inline std::string setName = "Set";
2220
2552
  public:
2553
+ From_Ruby() = default;
2554
+
2555
+ explicit From_Ruby(Arg* arg) : arg_(arg)
2556
+ {
2557
+ }
2558
+
2221
2559
  Convertible is_convertible(VALUE value)
2222
2560
  {
2223
2561
  switch (rb_type(value))
@@ -2274,6 +2612,7 @@ namespace Rice
2274
2612
  }
2275
2613
 
2276
2614
  private:
2615
+ Arg* arg_;
2277
2616
  std::set<T> converted_;
2278
2617
  };
2279
2618
  }
@@ -2319,8 +2658,8 @@ namespace Rice
2319
2658
 
2320
2659
  if (klassName.empty())
2321
2660
  {
2322
- std::string typeName = detail::typeName(typeid(SharedPtr_T));
2323
- klassName = detail::rubyClassName(typeName);
2661
+ detail::TypeMapper<SharedPtr_T> typeMapper;
2662
+ klassName = typeMapper.rubyName();
2324
2663
  }
2325
2664
 
2326
2665
  Module rb_mStd = define_module("Std");
@@ -2373,7 +2712,29 @@ namespace Rice::detail
2373
2712
  {
2374
2713
  static bool verify()
2375
2714
  {
2376
- return Type<T>::verify();
2715
+ if constexpr (std::is_fundamental_v<T>)
2716
+ {
2717
+ return Type<Pointer<T>>::verify();
2718
+ return Type<Buffer<T>>::verify();
2719
+ }
2720
+ else
2721
+ {
2722
+ return Type<T>::verify();
2723
+ }
2724
+ }
2725
+
2726
+ static VALUE rubyKlass()
2727
+ {
2728
+ if (Data_Type<std::shared_ptr<T>>::is_defined())
2729
+ {
2730
+ std::pair<VALUE, rb_data_type_t*> pair = Registries::instance.types.getType<std::shared_ptr<T>>();
2731
+ return pair.first;
2732
+ }
2733
+ else
2734
+ {
2735
+ TypeMapper<T> typeMapper;
2736
+ return typeMapper.rubyKlass();
2737
+ }
2377
2738
  }
2378
2739
  };
2379
2740
 
@@ -2381,11 +2742,17 @@ namespace Rice::detail
2381
2742
  class To_Ruby<std::shared_ptr<T>>
2382
2743
  {
2383
2744
  public:
2745
+ To_Ruby() = default;
2746
+
2747
+ explicit To_Ruby(Arg* arv)
2748
+ {
2749
+ }
2750
+
2384
2751
  VALUE convert(std::shared_ptr<T>& data)
2385
2752
  {
2386
2753
  if constexpr (std::is_fundamental_v<T>)
2387
2754
  {
2388
- return detail::wrap(Data_Type<T>::klass(), Data_Type<T>::ruby_data_type(), data, true);
2755
+ return detail::wrap<std::shared_ptr<T>>(Data_Type<Pointer<T>>::klass(), Data_Type<Pointer<T>>::ruby_data_type(), data, true);
2389
2756
  }
2390
2757
  else
2391
2758
  {
@@ -2397,7 +2764,7 @@ namespace Rice::detail
2397
2764
  {
2398
2765
  if constexpr (std::is_fundamental_v<T>)
2399
2766
  {
2400
- return detail::wrap(Data_Type<T>::klass(), Data_Type<T>::ruby_data_type(), data, true);
2767
+ return detail::wrap<std::shared_ptr<T>>(Data_Type<Pointer<T>>::klass(), Data_Type<Pointer<T>>::ruby_data_type(), data, true);
2401
2768
  }
2402
2769
  else
2403
2770
  {
@@ -2442,10 +2809,10 @@ namespace Rice::detail
2442
2809
  std::shared_ptr<T>* ptr = unwrap<std::shared_ptr<T>>(value, Data_Type<std::shared_ptr<T>>::ruby_data_type(), false);
2443
2810
  return *ptr;
2444
2811
  }
2445
- else if constexpr (std::is_fundamental_v<T>)
2812
+ else if (std::is_fundamental_v<T>)
2446
2813
  {
2447
2814
  // Get the wrapper again to validate T's type
2448
- Wrapper<std::shared_ptr<T>>* wrapper = getWrapper<Wrapper<std::shared_ptr<T>>>(value, Data_Type<T>::ruby_data_type());
2815
+ Wrapper<std::shared_ptr<T>>* wrapper = getWrapper<Wrapper<std::shared_ptr<T>>>(value, Data_Type<Pointer<T>>::ruby_data_type());
2449
2816
  return wrapper->data();
2450
2817
  }
2451
2818
  else
@@ -2463,16 +2830,15 @@ namespace Rice::detail
2463
2830
  class To_Ruby<std::shared_ptr<T>&>
2464
2831
  {
2465
2832
  public:
2833
+ To_Ruby() = default;
2834
+
2835
+ explicit To_Ruby(Arg* arg)
2836
+ {
2837
+ }
2838
+
2466
2839
  VALUE convert(std::shared_ptr<T>& data)
2467
2840
  {
2468
- if constexpr (std::is_fundamental_v<T>)
2469
- {
2470
- return detail::wrap(Data_Type<T>::klass(), Data_Type<T>::ruby_data_type(), data, true);
2471
- }
2472
- else
2473
- {
2474
- return detail::wrap<std::shared_ptr<T>>(Data_Type<T>::klass(), Data_Type<T>::ruby_data_type(), data, true);
2475
- }
2841
+ return detail::wrap(Data_Type<T>::klass(), Data_Type<T>::ruby_data_type(), data, true);
2476
2842
  }
2477
2843
  };
2478
2844
 
@@ -2512,10 +2878,10 @@ namespace Rice::detail
2512
2878
  std::shared_ptr<T>* ptr = unwrap<std::shared_ptr<T>>(value, Data_Type<std::shared_ptr<T>>::ruby_data_type(), false);
2513
2879
  return *ptr;
2514
2880
  }
2515
- else if constexpr (std::is_fundamental_v<T>)
2881
+ else if (std::is_fundamental_v<T>)
2516
2882
  {
2517
2883
  // Get the wrapper again to validate T's type
2518
- Wrapper<std::shared_ptr<T>>* wrapper = getWrapper<Wrapper<std::shared_ptr<T>>>(value, Data_Type<T>::ruby_data_type());
2884
+ Wrapper<std::shared_ptr<T>>* wrapper = getWrapper<Wrapper<std::shared_ptr<T>>>(value, Data_Type<Pointer<T>>::ruby_data_type());
2519
2885
  return wrapper->data();
2520
2886
  }
2521
2887
  else
@@ -2557,42 +2923,65 @@ namespace Rice::detail
2557
2923
  auto indices = std::make_index_sequence<std::tuple_size_v<std::tuple<Types...>>>{};
2558
2924
  return verifyTypes(indices);
2559
2925
  }
2926
+
2927
+ static VALUE rubyKlass()
2928
+ {
2929
+ return rb_cArray;
2930
+ }
2560
2931
  };
2561
2932
 
2562
2933
  template<typename...Types>
2563
2934
  class To_Ruby<std::tuple<Types...>>
2564
2935
  {
2565
2936
  public:
2566
- static VALUE convert(const std::tuple<Types...>& data, bool takeOwnership = false)
2937
+ To_Ruby() = default;
2938
+
2939
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
2940
+ {
2941
+ }
2942
+
2943
+ VALUE convert(const std::tuple<Types...>& data)
2567
2944
  {
2568
2945
  Array result;
2569
2946
 
2570
2947
  for_each_tuple(data, [&](auto element)
2571
2948
  {
2572
- using Element_T = decltype(element);
2573
- result.push<Element_T>((Element_T)element);
2949
+ result.push(element, true);
2574
2950
  });
2575
2951
 
2576
2952
  return result.value();
2577
2953
  }
2954
+
2955
+ private:
2956
+ Return* returnInfo_ = nullptr;
2578
2957
  };
2579
2958
 
2580
2959
  template<typename...Types>
2581
2960
  class To_Ruby<std::tuple<Types...>&>
2582
2961
  {
2583
2962
  public:
2584
- static VALUE convert(const std::tuple<Types...>& data, bool takeOwnership = false)
2963
+ To_Ruby() = default;
2964
+
2965
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
2966
+ {
2967
+ }
2968
+
2969
+ VALUE convert(const std::tuple<Types...>& data)
2585
2970
  {
2586
2971
  Array result;
2587
2972
 
2588
- for_each_tuple(data, [&](auto& value)
2589
- {
2590
- VALUE element = detail::To_Ruby<decltype(value)>().convert(value);
2591
- result.push(element);
2592
- });
2973
+ bool isOwner = (this->returnInfo_ && this->returnInfo_->isOwner());
2974
+
2975
+ for_each_tuple(data, [&](auto& element)
2976
+ {
2977
+ result.push(element, isOwner);
2978
+ });
2593
2979
 
2594
2980
  return result.value();
2595
2981
  }
2982
+
2983
+ private:
2984
+ Return* returnInfo_ = nullptr;
2596
2985
  };
2597
2986
 
2598
2987
  template<typename...Types>
@@ -2607,6 +2996,12 @@ namespace Rice::detail
2607
2996
  return (Type<std::tuple_element_t<I, Tuple_T>>::verify() && ...);
2608
2997
  }
2609
2998
 
2999
+ From_Ruby() = default;
3000
+
3001
+ explicit From_Ruby(Arg* arg)
3002
+ {
3003
+ }
3004
+
2610
3005
  Convertible is_convertible(VALUE value)
2611
3006
  {
2612
3007
  Convertible result = Convertible::None;
@@ -2756,27 +3151,37 @@ namespace Rice::detail
2756
3151
  return (Type<std::tuple_element_t<I, Tuple_T>>::verify() && ...);
2757
3152
  }
2758
3153
 
2759
- template<std::size_t... I>
2760
3154
  constexpr static bool verify()
2761
3155
  {
2762
3156
  auto indices = std::make_index_sequence<std::variant_size_v<std::variant<Types...>>>{};
2763
3157
  return verifyTypes(indices);
2764
3158
  }
3159
+
3160
+ static VALUE rubyKlass()
3161
+ {
3162
+ // There is no direct mapping to Ruby, so just return Object
3163
+ return rb_cObject;
3164
+ }
2765
3165
  };
2766
3166
 
2767
3167
  template<typename...Types>
2768
3168
  class To_Ruby<std::variant<Types...>>
2769
3169
  {
2770
3170
  public:
3171
+ To_Ruby() = default;
3172
+
3173
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
3174
+ {
3175
+ }
2771
3176
 
2772
3177
  template<typename U, typename V>
2773
- static VALUE convertElement(U& data, bool takeOwnership)
3178
+ VALUE convertElement(U& data, bool takeOwnership)
2774
3179
  {
2775
3180
  return To_Ruby<V>().convert(std::forward<V>(std::get<V>(data)));
2776
3181
  }
2777
3182
 
2778
3183
  template<typename U, std::size_t... I>
2779
- static VALUE convertIterator(U& data, bool takeOwnership, std::index_sequence<I...>& indices)
3184
+ VALUE convertIterator(U& data, bool takeOwnership, std::index_sequence<I...>& indices)
2780
3185
  {
2781
3186
  // Create a tuple of the variant types so we can look over the tuple's types
2782
3187
  using Tuple_T = std::tuple<Types...>;
@@ -2819,26 +3224,36 @@ namespace Rice::detail
2819
3224
  }
2820
3225
 
2821
3226
  template<typename U>
2822
- static VALUE convert(U& data, bool takeOwnership = false)
3227
+ VALUE convert(U& data)
2823
3228
  {
2824
3229
  auto indices = std::make_index_sequence<std::variant_size_v<std::variant<Types...>>>{};
2825
- return convertIterator(data, takeOwnership, indices);
3230
+ return convertIterator(data, true, indices);
2826
3231
  }
2827
3232
 
2828
3233
  template<typename U>
2829
- static VALUE convert(U&& data, bool takeOwnership = false)
3234
+ VALUE convert(U&& data)
2830
3235
  {
3236
+ bool isOwner = true;
2831
3237
  auto indices = std::make_index_sequence<std::variant_size_v<std::variant<Types...>>>{};
2832
- return convertIterator(data, takeOwnership, indices);
3238
+ return convertIterator(data, isOwner, indices);
2833
3239
  }
3240
+
3241
+ private:
3242
+ Return* returnInfo_ = nullptr;
2834
3243
  };
2835
3244
 
2836
3245
  template<typename...Types>
2837
3246
  class To_Ruby<std::variant<Types...>&>
2838
3247
  {
2839
3248
  public:
3249
+ To_Ruby() = default;
3250
+
3251
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
3252
+ {
3253
+ }
3254
+
2840
3255
  template<typename U, typename V>
2841
- static VALUE convertElement(U& data, bool takeOwnership)
3256
+ VALUE convertElement(U& data, bool takeOwnership)
2842
3257
  {
2843
3258
  if constexpr (std::is_const_v<U>)
2844
3259
  {
@@ -2851,7 +3266,7 @@ namespace Rice::detail
2851
3266
  }
2852
3267
 
2853
3268
  template<typename U, std::size_t... I>
2854
- static VALUE convertIterator(U& data, bool takeOwnership, std::index_sequence<I...>& indices)
3269
+ VALUE convertIterator(U& data, bool takeOwnership, std::index_sequence<I...>& indices)
2855
3270
  {
2856
3271
  // Create a tuple of the variant types so we can look over the tuple's types
2857
3272
  using Tuple_T = std::tuple<Types...>;
@@ -2875,17 +3290,27 @@ namespace Rice::detail
2875
3290
  }
2876
3291
 
2877
3292
  template<typename U>
2878
- static VALUE convert(U& data, bool takeOwnership = false)
3293
+ VALUE convert(U& data)
2879
3294
  {
3295
+ bool isOwner = (this->returnInfo_ && this->returnInfo_->isOwner());
2880
3296
  auto indices = std::make_index_sequence<std::variant_size_v<std::variant<Types...>>>{};
2881
- return convertIterator(data, takeOwnership, indices);
3297
+ return convertIterator(data, isOwner, indices);
2882
3298
  }
3299
+
3300
+ private:
3301
+ Return* returnInfo_ = nullptr;
2883
3302
  };
2884
3303
 
2885
3304
  template<typename...Types>
2886
3305
  class From_Ruby<std::variant<Types...>>
2887
3306
  {
2888
3307
  public:
3308
+ From_Ruby() = default;
3309
+
3310
+ explicit From_Ruby(Arg* arg)
3311
+ {
3312
+ }
3313
+
2889
3314
  Convertible is_convertible(VALUE value)
2890
3315
  {
2891
3316
  Convertible result = Convertible::None;
@@ -2972,6 +3397,12 @@ namespace Rice::detail
2972
3397
  class From_Ruby<std::variant<Types...>&> : public From_Ruby<std::variant<Types...>>
2973
3398
  {
2974
3399
  public:
3400
+ From_Ruby() = default;
3401
+
3402
+ explicit From_Ruby(Arg* arg)
3403
+ {
3404
+ }
3405
+
2975
3406
  std::variant<Types...>& convert(VALUE value)
2976
3407
  {
2977
3408
  int index = this->figureIndex(value);
@@ -3037,6 +3468,12 @@ namespace Rice::detail
3037
3468
  class To_Ruby<std::unique_ptr<T>>
3038
3469
  {
3039
3470
  public:
3471
+ To_Ruby() = default;
3472
+
3473
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
3474
+ {
3475
+ }
3476
+
3040
3477
  VALUE convert(std::unique_ptr<T>& data)
3041
3478
  {
3042
3479
  std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(*data);
@@ -3048,17 +3485,29 @@ namespace Rice::detail
3048
3485
  std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(*data);
3049
3486
  return detail::wrap<std::unique_ptr<T>>(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
3050
3487
  }
3488
+
3489
+ private:
3490
+ Return* returnInfo_ = nullptr;
3051
3491
  };
3052
3492
 
3053
3493
  template <typename T>
3054
3494
  class To_Ruby<std::unique_ptr<T>&>
3055
3495
  {
3056
3496
  public:
3497
+ To_Ruby() = default;
3498
+
3499
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
3500
+ {
3501
+ }
3502
+
3057
3503
  VALUE convert(std::unique_ptr<T>& data)
3058
3504
  {
3059
3505
  std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(*data);
3060
- return detail::wrap<std::unique_ptr<T>>(rubyTypeInfo.first, rubyTypeInfo.second, std::move(data), true);
3506
+ return detail::wrap<std::unique_ptr<T>>(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
3061
3507
  }
3508
+
3509
+ private:
3510
+ Return* returnInfo_ = nullptr;
3062
3511
  };
3063
3512
 
3064
3513
  template <typename T>
@@ -3071,6 +3520,12 @@ namespace Rice::detail
3071
3520
  return dynamic_cast<Wrapper<std::unique_ptr<T>>*>(wrapper);
3072
3521
  }
3073
3522
 
3523
+ From_Ruby() = default;
3524
+
3525
+ explicit From_Ruby(Arg* arg)
3526
+ {
3527
+ }
3528
+
3074
3529
  Convertible is_convertible(VALUE value)
3075
3530
  {
3076
3531
  if (!is_same_smart_ptr(value))
@@ -3108,6 +3563,12 @@ namespace Rice::detail
3108
3563
  return dynamic_cast<Wrapper<std::unique_ptr<T>>*>(wrapper);
3109
3564
  }
3110
3565
 
3566
+ From_Ruby() = default;
3567
+
3568
+ explicit From_Ruby(Arg* arg)
3569
+ {
3570
+ }
3571
+
3111
3572
  Convertible is_convertible(VALUE value)
3112
3573
  {
3113
3574
  if (!is_same_smart_ptr(value))
@@ -3140,7 +3601,21 @@ namespace Rice::detail
3140
3601
  {
3141
3602
  static bool verify()
3142
3603
  {
3143
- return Type<T>::verify();
3604
+ if constexpr (std::is_fundamental_v<T>)
3605
+ {
3606
+ return Type<Pointer<T>>::verify();
3607
+ return Type<Buffer<T>>::verify();
3608
+ }
3609
+ else
3610
+ {
3611
+ return Type<T>::verify();
3612
+ }
3613
+ }
3614
+
3615
+ static VALUE rubyKlass()
3616
+ {
3617
+ TypeMapper<T> typeMapper;
3618
+ return typeMapper.rubyKlass();
3144
3619
  }
3145
3620
  };
3146
3621
  }
@@ -3177,8 +3652,7 @@ namespace Rice
3177
3652
  UnorderedMapHelper(Data_Type<T> klass) : klass_(klass)
3178
3653
  {
3179
3654
  this->register_pair();
3180
- this->define_constructor();
3181
- this->define_copyable_methods();
3655
+ this->define_constructors();
3182
3656
  this->define_capacity_methods();
3183
3657
  this->define_access_methods();
3184
3658
  this->define_comparable_methods();
@@ -3195,27 +3669,13 @@ namespace Rice
3195
3669
  define_pair<const Key_T, T>();
3196
3670
  }
3197
3671
 
3198
- void define_constructor()
3672
+ void define_constructors()
3199
3673
  {
3200
3674
  klass_.define_constructor(Constructor<T>());
3201
- }
3202
3675
 
3203
- void define_copyable_methods()
3204
- {
3205
- if constexpr (std::is_copy_constructible_v<Value_T>)
3206
- {
3207
- klass_.define_method("copy", [](T& unordered_map) -> T
3208
- {
3209
- return unordered_map;
3210
- });
3211
- }
3212
- else
3676
+ if constexpr (std::is_copy_constructible_v<Key_T> && std::is_copy_constructible_v<Value_T>)
3213
3677
  {
3214
- klass_.define_method("copy", [](T& unordered_map) -> T
3215
- {
3216
- throw std::runtime_error("Cannot copy unordered_maps with non-copy constructible types");
3217
- return unordered_map;
3218
- });
3678
+ klass_.define_constructor(Constructor<T, const T&>());
3219
3679
  }
3220
3680
  }
3221
3681
 
@@ -3398,8 +3858,8 @@ namespace Rice
3398
3858
 
3399
3859
  if (klassName.empty())
3400
3860
  {
3401
- std::string typeName = detail::typeName(typeid(UnorderedMap_T));
3402
- klassName = detail::rubyClassName(typeName);
3861
+ detail::TypeMapper<UnorderedMap_T> typeMapper;
3862
+ klassName = typeMapper.rubyName();
3403
3863
  }
3404
3864
 
3405
3865
  Module rb_mStd = define_module("Std");
@@ -3576,6 +4036,12 @@ namespace Rice
3576
4036
  class From_Ruby<std::unordered_map<T, U>*>
3577
4037
  {
3578
4038
  public:
4039
+ From_Ruby() = default;
4040
+
4041
+ explicit From_Ruby(Arg* arg) : arg_(arg)
4042
+ {
4043
+ }
4044
+
3579
4045
  Convertible is_convertible(VALUE value)
3580
4046
  {
3581
4047
  switch (rb_type(value))
@@ -3621,6 +4087,7 @@ namespace Rice
3621
4087
  }
3622
4088
 
3623
4089
  private:
4090
+ Arg* arg_;
3624
4091
  std::unordered_map<T, U> converted_;
3625
4092
  };
3626
4093
  }
@@ -3676,12 +4143,10 @@ namespace Rice
3676
4143
  // Helper method to translate Ruby indices to vector indices
3677
4144
  Difference_T normalizeIndex(Size_T size, Difference_T index, bool enforceBounds = false)
3678
4145
  {
3679
- // Negative indices mean count from the right. Note that negative indices
3680
- // wrap around!
3681
- if (index < 0)
4146
+ // Negative indices mean count from the right
4147
+ if (index < 0 && (-index <= size))
3682
4148
  {
3683
- index = ((-index) % size);
3684
- index = index > 0 ? size - index : index;
4149
+ index = size + index;
3685
4150
  }
3686
4151
 
3687
4152
  if (enforceBounds && (index < 0 || index >= (Difference_T)size))
@@ -3694,9 +4159,13 @@ namespace Rice
3694
4159
 
3695
4160
  void define_constructors()
3696
4161
  {
3697
- klass_.define_constructor(Constructor<T>())
3698
- .define_constructor(Constructor<T, Size_T, const Parameter_T>())
3699
- .define_constructor(Constructor<T, const T&>());
4162
+ klass_.define_constructor(Constructor<T>());
4163
+
4164
+ if constexpr (std::is_copy_constructible_v<Value_T>)
4165
+ {
4166
+ klass_.define_constructor(Constructor<T, const T&>())
4167
+ .define_constructor(Constructor<T, Size_T, const Parameter_T>());
4168
+ }
3700
4169
 
3701
4170
  if constexpr (std::is_default_constructible_v<Value_T>)
3702
4171
  {
@@ -3758,42 +4227,85 @@ namespace Rice
3758
4227
 
3759
4228
  void define_access_methods()
3760
4229
  {
3761
- // Access methods
3762
- klass_.define_method("first", [](const T& vector) -> std::optional<Value_T>
4230
+ if constexpr (!std::is_same_v<Value_T, bool>)
3763
4231
  {
3764
- if (vector.size() > 0)
3765
- {
3766
- return vector.front();
3767
- }
3768
- else
4232
+ // Access methods
4233
+ klass_.define_method("first", [](T& vector) -> std::optional<std::reference_wrapper<Value_T>>
3769
4234
  {
3770
- return std::nullopt;
3771
- }
3772
- })
3773
- .define_method("last", [](const T& vector) -> std::optional<Value_T>
3774
- {
3775
- if (vector.size() > 0)
4235
+ if (vector.size() > 0)
4236
+ {
4237
+ return vector.front();
4238
+ }
4239
+ else
4240
+ {
4241
+ return std::nullopt;
4242
+ }
4243
+ })
4244
+ .define_method("last", [](T& vector) -> std::optional<std::reference_wrapper<Value_T>>
3776
4245
  {
3777
- return vector.back();
3778
- }
3779
- else
4246
+ if (vector.size() > 0)
4247
+ {
4248
+ return vector.back();
4249
+ }
4250
+ else
4251
+ {
4252
+ return std::nullopt;
4253
+ }
4254
+ })
4255
+ .define_method("[]", [this](T& vector, Difference_T index) -> std::optional<std::reference_wrapper<Value_T>>
3780
4256
  {
3781
- return std::nullopt;
3782
- }
3783
- })
3784
- .define_method("[]", [this](const T& vector, Difference_T index) -> std::optional<Value_T>
4257
+ index = normalizeIndex(vector.size(), index);
4258
+ if (index < 0 || index >= (Difference_T)vector.size())
4259
+ {
4260
+ return std::nullopt;
4261
+ }
4262
+ else
4263
+ {
4264
+ return vector[index];
4265
+ }
4266
+ })
4267
+ .template define_method<Value_T*(T::*)()>("data", &T::data, Return().setBuffer());
4268
+ }
4269
+ else
3785
4270
  {
3786
- index = normalizeIndex(vector.size(), index);
3787
- if (index < 0 || index >= (Difference_T)vector.size())
4271
+ // Access methods
4272
+ klass_.define_method("first", [](T& vector) -> std::optional<Value_T>
3788
4273
  {
3789
- return std::nullopt;
3790
- }
3791
- else
4274
+ if (vector.size() > 0)
4275
+ {
4276
+ return vector.front();
4277
+ }
4278
+ else
4279
+ {
4280
+ return std::nullopt;
4281
+ }
4282
+ })
4283
+ .define_method("last", [](T& vector) -> std::optional<Value_T>
3792
4284
  {
3793
- return vector[index];
3794
- }
3795
- })
3796
- .define_method("[]", [this](const T& vector, Difference_T start, Difference_T length) -> VALUE
4285
+ if (vector.size() > 0)
4286
+ {
4287
+ return vector.back();
4288
+ }
4289
+ else
4290
+ {
4291
+ return std::nullopt;
4292
+ }
4293
+ })
4294
+ .define_method("[]", [this](T& vector, Difference_T index) -> std::optional<Value_T>
4295
+ {
4296
+ index = normalizeIndex(vector.size(), index);
4297
+ if (index < 0 || index >= (Difference_T)vector.size())
4298
+ {
4299
+ return std::nullopt;
4300
+ }
4301
+ else
4302
+ {
4303
+ return vector[index];
4304
+ }
4305
+ });
4306
+ }
4307
+
4308
+ klass_.define_method("[]", [this](T& vector, Difference_T start, Difference_T length) -> VALUE
3797
4309
  {
3798
4310
  start = normalizeIndex(vector.size(), start);
3799
4311
  if (start < 0 || start >= (Difference_T)vector.size())
@@ -3812,25 +4324,19 @@ namespace Rice
3812
4324
  }
3813
4325
 
3814
4326
  auto finish = vector.begin() + start + length;
3815
- T slice(begin, finish);
3816
4327
 
3817
4328
  VALUE result = rb_ary_new();
3818
- std::for_each(slice.begin(), slice.end(), [&result](const Reference_T element)
4329
+ for (auto iter = begin; iter != finish; iter++)
3819
4330
  {
3820
- VALUE value = detail::To_Ruby<Parameter_T>().convert(element);
4331
+ const Reference_T element = *iter;
4332
+ VALUE value = detail::To_Ruby<Reference_T>().convert(element);
3821
4333
  rb_ary_push(result, value);
3822
- });
4334
+ }
3823
4335
 
3824
4336
  return result;
3825
4337
  }
3826
4338
  }, Return().setValue());
3827
4339
 
3828
- if constexpr (!std::is_same_v<Value_T, bool>)
3829
- {
3830
- define_buffer<Value_T>();
3831
- klass_.template define_method<Value_T*(T::*)()>("data", &T::data);
3832
- }
3833
-
3834
4340
  rb_define_alias(klass_, "at", "[]");
3835
4341
  }
3836
4342
 
@@ -3840,35 +4346,39 @@ namespace Rice
3840
4346
  if constexpr (detail::is_comparable_v<T>)
3841
4347
  {
3842
4348
  klass_.define_method("delete", [](T& vector, Parameter_T element) -> std::optional<Value_T>
4349
+ {
4350
+ auto iter = std::find(vector.begin(), vector.end(), element);
4351
+ if (iter == vector.end())
3843
4352
  {
3844
- auto iter = std::find(vector.begin(), vector.end(), element);
3845
- if (iter == vector.end())
3846
- {
3847
- return std::nullopt;
3848
- }
3849
- else
3850
- {
3851
- Value_T result = *iter;
3852
- vector.erase(iter);
3853
- return result;
3854
- }
3855
- })
3856
- .define_method("include?", [](T& vector, Parameter_T element)
4353
+ return std::nullopt;
4354
+ }
4355
+ else if constexpr (std::is_copy_assignable_v<Value_T>)
3857
4356
  {
3858
- return std::find(vector.begin(), vector.end(), element) != vector.end();
3859
- })
4357
+ Value_T result = *iter;
4358
+ vector.erase(iter);
4359
+ return result;
4360
+ }
4361
+ else
4362
+ {
4363
+ return std::nullopt;
4364
+ }
4365
+ })
4366
+ .define_method("include?", [](T& vector, Parameter_T element)
4367
+ {
4368
+ return std::find(vector.begin(), vector.end(), element) != vector.end();
4369
+ })
3860
4370
  .define_method("index", [](T& vector, Parameter_T element) -> std::optional<Difference_T>
4371
+ {
4372
+ auto iter = std::find(vector.begin(), vector.end(), element);
4373
+ if (iter == vector.end())
3861
4374
  {
3862
- auto iter = std::find(vector.begin(), vector.end(), element);
3863
- if (iter == vector.end())
3864
- {
3865
- return std::nullopt;
3866
- }
3867
- else
3868
- {
3869
- return iter - vector.begin();
3870
- }
3871
- });
4375
+ return std::nullopt;
4376
+ }
4377
+ else
4378
+ {
4379
+ return iter - vector.begin();
4380
+ }
4381
+ });
3872
4382
  }
3873
4383
  else
3874
4384
  {
@@ -3890,45 +4400,65 @@ namespace Rice
3890
4400
  void define_modify_methods()
3891
4401
  {
3892
4402
  klass_.define_method("clear", &T::clear)
3893
- .define_method("delete_at", [](T& vector, const size_t& pos)
4403
+ .define_method("delete_at", [](T& vector, const size_t& pos) -> std::optional<Value_T>
4404
+ {
4405
+ auto iter = vector.begin() + pos;
4406
+
4407
+ if constexpr (std::is_copy_assignable_v<Value_T>)
3894
4408
  {
3895
- auto iter = vector.begin() + pos;
3896
4409
  Value_T result = *iter;
3897
4410
  vector.erase(iter);
3898
4411
  return result;
3899
- })
4412
+ }
4413
+ else
4414
+ {
4415
+ vector.erase(iter);
4416
+ return std::nullopt;
4417
+ }
4418
+ })
3900
4419
  .define_method("insert", [this](T& vector, Difference_T index, Parameter_T element) -> T&
4420
+ {
4421
+ int normalized = normalizeIndex(vector.size(), index, true);
4422
+ // For a Ruby array a positive index means insert the element before the index. But
4423
+ // a negative index means insert the element *after* the index. std::vector
4424
+ // inserts *before* the index. So add 1 if this is a negative index.
4425
+ if (index < 0)
3901
4426
  {
3902
- index = normalizeIndex(vector.size(), index, true);
3903
- auto iter = vector.begin() + index;
3904
- vector.insert(iter, element);
3905
- return vector;
3906
- })
4427
+ normalized++;
4428
+ }
4429
+ auto iter = vector.begin() + normalized;
4430
+ vector.insert(iter, std::move(element));
4431
+ return vector;
4432
+ })
3907
4433
  .define_method("pop", [](T& vector) -> std::optional<Value_T>
4434
+ {
4435
+ if constexpr (!std::is_copy_assignable_v<Value_T>)
3908
4436
  {
3909
- if (vector.size() > 0)
3910
- {
3911
- Value_T result = vector.back();
3912
- vector.pop_back();
3913
- return result;
3914
- }
3915
- else
3916
- {
3917
- return std::nullopt;
3918
- }
3919
- })
3920
- .define_method("push", [](T& vector, Parameter_T element) -> T&
4437
+ vector.pop_back();
4438
+ return std::nullopt;
4439
+ }
4440
+ else if (vector.empty())
3921
4441
  {
3922
- vector.push_back(element);
3923
- return vector;
3924
- })
3925
- .define_method("shrink_to_fit", &T::shrink_to_fit)
3926
- .define_method("[]=", [this](T& vector, Difference_T index, Parameter_T element) -> Parameter_T
4442
+ return std::nullopt;
4443
+ }
4444
+ else
3927
4445
  {
3928
- index = normalizeIndex(vector.size(), index, true);
3929
- vector[index] = element;
3930
- return element;
3931
- });
4446
+ Value_T result = vector.back();
4447
+ vector.pop_back();
4448
+ return result;
4449
+ }
4450
+ })
4451
+ .define_method("push", [](T& vector, Parameter_T element) -> T&
4452
+ {
4453
+ vector.push_back(std::move(element));
4454
+ return vector;
4455
+ })
4456
+ .define_method("shrink_to_fit", &T::shrink_to_fit)
4457
+ .define_method("[]=", [this](T& vector, Difference_T index, Parameter_T element) -> void
4458
+ {
4459
+ index = normalizeIndex(vector.size(), index, true);
4460
+ vector[index] = std::move(element);
4461
+ });
3932
4462
 
3933
4463
  rb_define_alias(klass_, "push_back", "push");
3934
4464
  rb_define_alias(klass_, "<<", "push");
@@ -3949,7 +4479,7 @@ namespace Rice
3949
4479
  VALUE result = rb_ary_new();
3950
4480
  std::for_each(vector.begin(), vector.end(), [&result](const Reference_T element)
3951
4481
  {
3952
- VALUE value = detail::To_Ruby<Parameter_T>().convert(element);
4482
+ VALUE value = detail::To_Ruby<Reference_T>().convert(element);
3953
4483
  rb_ary_push(result, value);
3954
4484
  });
3955
4485
 
@@ -4007,8 +4537,8 @@ namespace Rice
4007
4537
 
4008
4538
  if (klassName.empty())
4009
4539
  {
4010
- std::string typeName = detail::typeName(typeid(Vector_T));
4011
- klassName = detail::rubyClassName(typeName);
4540
+ detail::TypeMapper<Vector_T> typeMapper;
4541
+ klassName = typeMapper.rubyName();
4012
4542
  }
4013
4543
 
4014
4544
  Module rb_mStd = define_module("Std");
@@ -4160,6 +4690,12 @@ namespace Rice
4160
4690
  class From_Ruby<std::vector<T>*>
4161
4691
  {
4162
4692
  public:
4693
+ From_Ruby() = default;
4694
+
4695
+ explicit From_Ruby(Arg* arg) : arg_(arg)
4696
+ {
4697
+ }
4698
+
4163
4699
  Convertible is_convertible(VALUE value)
4164
4700
  {
4165
4701
  switch (rb_type(value))
@@ -4207,6 +4743,7 @@ namespace Rice
4207
4743
  }
4208
4744
 
4209
4745
  private:
4746
+ Arg* arg_;
4210
4747
  std::vector<T> converted_;
4211
4748
  };
4212
4749
  }
@@ -4218,10 +4755,19 @@ namespace Rice
4218
4755
  class To_Ruby<std::vector<bool>::reference>
4219
4756
  {
4220
4757
  public:
4758
+ To_Ruby() = default;
4759
+
4760
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
4761
+ {
4762
+ }
4763
+
4221
4764
  VALUE convert(const std::vector<bool>::reference& value)
4222
4765
  {
4223
4766
  return value ? Qtrue : Qfalse;
4224
4767
  }
4768
+
4769
+ private:
4770
+ Return* returnInfo_ = nullptr;
4225
4771
  };
4226
4772
  }
4227
4773
  }