rice 4.6.1 → 4.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/CMakeLists.txt +0 -4
  4. data/Rakefile +2 -8
  5. data/bin/rice-doc.rb +212 -0
  6. data/bin/rice-rbs.rb +93 -0
  7. data/include/rice/rice.hpp +4972 -4015
  8. data/include/rice/stl.hpp +822 -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 +101 -82
  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 +2 -2
  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 +34 -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 -2
  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 +27 -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 +5 -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 +11 -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 +0 -55
  138. data/test/test_Data_Type.cpp +19 -30
  139. data/test/test_Enum.cpp +4 -46
  140. data/test/test_From_Ruby.cpp +88 -81
  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 +3 -3
  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_Tuple.cpp +1 -1
  152. data/test/test_Stl_UniquePtr.cpp +8 -0
  153. data/test/test_Stl_Unordered_Map.cpp +9 -9
  154. data/test/test_Stl_Variant.cpp +9 -3
  155. data/test/test_Stl_Vector.cpp +118 -13
  156. data/test/test_To_Ruby.cpp +35 -28
  157. data/test/test_Type.cpp +256 -53
  158. data/test/unittest.hpp +35 -0
  159. metadata +66 -34
  160. data/rice/Init.hpp +0 -8
  161. data/rice/Init.ipp +0 -8
  162. data/rice/detail/RubyFunction.hpp +0 -31
  163. data/rice/detail/RubyFunction.ipp +0 -77
  164. data/sample/callbacks/extconf.rb +0 -5
  165. data/sample/callbacks/sample_callbacks.cpp +0 -35
  166. data/sample/callbacks/test.rb +0 -28
  167. data/sample/enum/extconf.rb +0 -5
  168. data/sample/enum/sample_enum.cpp +0 -40
  169. data/sample/enum/test.rb +0 -8
  170. data/sample/inheritance/animals.cpp +0 -82
  171. data/sample/inheritance/extconf.rb +0 -5
  172. data/sample/inheritance/test.rb +0 -7
  173. data/sample/map/extconf.rb +0 -5
  174. data/sample/map/map.cpp +0 -73
  175. data/sample/map/test.rb +0 -7
  176. data/test/ext/t1/Foo.hpp +0 -10
  177. data/test/ext/t1/extconf.rb +0 -4
  178. data/test/ext/t1/t1.cpp +0 -13
  179. data/test/ext/t2/extconf.rb +0 -4
  180. data/test/ext/t2/t2.cpp +0 -11
  181. data/test/ruby/test_callbacks_sample.rb +0 -28
  182. data/test/ruby/test_multiple_extensions.rb +0 -18
  183. data/test/ruby/test_multiple_extensions_same_class.rb +0 -14
  184. data/test/ruby/test_multiple_extensions_with_inheritance.rb +0 -20
  185. /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,6 +434,11 @@ 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<>
@@ -323,12 +509,23 @@ namespace Rice::detail
323
509
  {
324
510
  return true;
325
511
  }
512
+
513
+ static VALUE rubyKlass()
514
+ {
515
+ return rb_cComplex;
516
+ }
326
517
  };
327
518
 
328
519
  template<typename T>
329
520
  class To_Ruby<std::complex<T>>
330
521
  {
331
522
  public:
523
+ To_Ruby() = default;
524
+
525
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
526
+ {
527
+ }
528
+
332
529
  VALUE convert(const std::complex<T>& data)
333
530
  {
334
531
  std::vector<VALUE> args(2);
@@ -336,12 +533,21 @@ namespace Rice::detail
336
533
  args[1] = To_Ruby<T>().convert(data.imag());
337
534
  return protect(rb_funcallv, rb_mKernel, rb_intern("Complex"), (int)args.size(), (const VALUE*)args.data());
338
535
  }
536
+
537
+ private:
538
+ Return* returnInfo_ = nullptr;
339
539
  };
340
540
 
341
541
  template<typename T>
342
542
  class To_Ruby<std::complex<T>&>
343
543
  {
344
544
  public:
545
+ To_Ruby() = default;
546
+
547
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
548
+ {
549
+ }
550
+
345
551
  VALUE convert(const std::complex<T>& data)
346
552
  {
347
553
  std::vector<VALUE> args(2);
@@ -349,12 +555,21 @@ namespace Rice::detail
349
555
  args[1] = To_Ruby<T>().convert(data.imag());
350
556
  return protect(rb_funcallv, rb_mKernel, rb_intern("Complex"), (int)args.size(), (const VALUE*)args.data());
351
557
  }
558
+
559
+ private:
560
+ Return* returnInfo_ = nullptr;
352
561
  };
353
562
 
354
563
  template<typename T>
355
564
  class From_Ruby<std::complex<T>>
356
565
  {
357
566
  public:
567
+ From_Ruby() = default;
568
+
569
+ explicit From_Ruby(Arg* arg)
570
+ {
571
+ }
572
+
358
573
  Convertible is_convertible(VALUE value)
359
574
  {
360
575
  switch (rb_type(value))
@@ -380,6 +595,12 @@ namespace Rice::detail
380
595
  class From_Ruby<std::complex<T>&>
381
596
  {
382
597
  public:
598
+ From_Ruby() = default;
599
+
600
+ explicit From_Ruby(Arg* arg)
601
+ {
602
+ }
603
+
383
604
  Convertible is_convertible(VALUE value)
384
605
  {
385
606
  switch (rb_type(value))
@@ -407,6 +628,46 @@ namespace Rice::detail
407
628
  }
408
629
 
409
630
 
631
+ // ========= filesystem.hpp =========
632
+
633
+
634
+ // --------- filesystem.ipp ---------
635
+ #include <filesystem>
636
+
637
+ namespace Rice
638
+ {
639
+ namespace stl
640
+ {
641
+ inline void define_filesystem_path()
642
+ {
643
+ Module rb_mStd = define_module("Std");
644
+ Module rb_mFileSystem = define_module_under(rb_mStd, "Filesystem");
645
+
646
+ define_class_under<std::filesystem::path>(rb_mFileSystem, "Path").
647
+ define_constructor(Constructor<std::filesystem::path>()).
648
+ define_constructor(Constructor<std::filesystem::path, std::string>());
649
+ }
650
+ }
651
+ }
652
+
653
+ namespace Rice::detail
654
+ {
655
+ template<>
656
+ struct Type<std::filesystem::path>
657
+ {
658
+ static bool verify()
659
+ {
660
+ if (!Data_Type<std::filesystem::path>::is_defined())
661
+ {
662
+ Rice::stl::define_filesystem_path();
663
+ }
664
+
665
+ return true;
666
+ }
667
+ };
668
+ }
669
+
670
+
410
671
  // ========= optional.hpp =========
411
672
 
412
673
 
@@ -422,23 +683,44 @@ namespace Rice::detail
422
683
  {
423
684
  return Type<intrinsic_type<T>>::verify();
424
685
  }
686
+
687
+ static VALUE rubyKlass()
688
+ {
689
+ TypeMapper<T> typeMapper;
690
+ return typeMapper.rubyKlass();
691
+ }
425
692
  };
426
693
 
427
694
  template<>
428
695
  class To_Ruby<std::nullopt_t>
429
696
  {
430
697
  public:
698
+ To_Ruby() = default;
699
+
700
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
701
+ {
702
+ }
703
+
431
704
  VALUE convert(const std::nullopt_t& _)
432
705
  {
433
706
  return Qnil;
434
707
  }
708
+
709
+ private:
710
+ Return* returnInfo_ = nullptr;
435
711
  };
436
712
 
437
713
  template<typename T>
438
714
  class To_Ruby<std::optional<T>>
439
715
  {
440
716
  public:
441
- static VALUE convert(const std::optional<T>& data, bool takeOwnership = false)
717
+ To_Ruby() = default;
718
+
719
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
720
+ {
721
+ }
722
+
723
+ VALUE convert(std::optional<T>& data)
442
724
  {
443
725
  if (data.has_value())
444
726
  {
@@ -449,13 +731,22 @@ namespace Rice::detail
449
731
  return Qnil;
450
732
  }
451
733
  }
734
+
735
+ private:
736
+ Return* returnInfo_ = nullptr;
452
737
  };
453
738
 
454
739
  template<typename T>
455
740
  class To_Ruby<std::optional<T>&>
456
741
  {
457
742
  public:
458
- static VALUE convert(const std::optional<T>& data, bool takeOwnership = false)
743
+ To_Ruby() = default;
744
+
745
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
746
+ {
747
+ }
748
+
749
+ VALUE convert(const std::optional<T>& data)
459
750
  {
460
751
  if (data.has_value())
461
752
  {
@@ -466,12 +757,21 @@ namespace Rice::detail
466
757
  return Qnil;
467
758
  }
468
759
  }
760
+
761
+ private:
762
+ Return* returnInfo_ = nullptr;
469
763
  };
470
764
 
471
765
  template<typename T>
472
766
  class From_Ruby<std::optional<T>>
473
767
  {
474
768
  public:
769
+ From_Ruby() = default;
770
+
771
+ explicit From_Ruby(Arg* arg)
772
+ {
773
+ }
774
+
475
775
  Convertible is_convertible(VALUE value)
476
776
  {
477
777
  switch (rb_type(value))
@@ -501,6 +801,12 @@ namespace Rice::detail
501
801
  class From_Ruby<std::optional<T>&>
502
802
  {
503
803
  public:
804
+ From_Ruby() = default;
805
+
806
+ explicit From_Ruby(Arg* arg)
807
+ {
808
+ }
809
+
504
810
  Convertible is_convertible(VALUE value)
505
811
  {
506
812
  switch (rb_type(value))
@@ -546,22 +852,43 @@ namespace Rice::detail
546
852
  {
547
853
  return Type<T>::verify();
548
854
  }
855
+
856
+ static VALUE rubyKlass()
857
+ {
858
+ TypeMapper<T> typeMapper;
859
+ return typeMapper.rubyKlass();
860
+ }
549
861
  };
550
862
 
551
863
  template<typename T>
552
864
  class To_Ruby<std::reference_wrapper<T>>
553
865
  {
554
866
  public:
555
- VALUE convert(const std::reference_wrapper<T>& data, bool takeOwnership = false)
867
+ To_Ruby() = default;
868
+
869
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
870
+ {
871
+ }
872
+
873
+ VALUE convert(const std::reference_wrapper<T>& data)
556
874
  {
557
875
  return To_Ruby<T&>().convert(data.get());
558
876
  }
877
+
878
+ private:
879
+ Return* returnInfo_ = nullptr;
559
880
  };
560
881
 
561
882
  template<typename T>
562
883
  class From_Ruby<std::reference_wrapper<T>>
563
884
  {
564
885
  public:
886
+ From_Ruby() = default;
887
+
888
+ explicit From_Ruby(Arg* arg)
889
+ {
890
+ }
891
+
565
892
  Convertible is_convertible(VALUE value)
566
893
  {
567
894
  return this->converter_.is_convertible(value);
@@ -600,78 +927,43 @@ namespace Rice
600
927
  public:
601
928
  PairHelper(Data_Type<T> klass) : klass_(klass)
602
929
  {
603
- this->define_constructor();
604
- this->define_copyable_methods();
605
- this->define_access_methods();
606
- this->define_modify_methods();
930
+ this->define_constructors();
931
+ this->define_attributes();
607
932
  this->define_to_s();
608
933
  }
609
934
 
610
935
  private:
611
- void define_constructor()
936
+ void define_constructors()
612
937
  {
613
- klass_.define_constructor(Constructor<T, typename T::first_type&, typename T::second_type&>());
938
+ klass_.define_constructor(Constructor<T>())
939
+ .define_constructor(Constructor<T, typename T::first_type&, typename T::second_type&>());
940
+
941
+ if constexpr (std::is_copy_constructible_v<typename T::first_type> && std::is_copy_constructible_v<typename T::second_type>)
942
+ {
943
+ klass_.define_constructor(Constructor<T, const T&>());
944
+ }
614
945
  }
615
946
 
616
- void define_copyable_methods()
947
+ void define_attributes()
617
948
  {
618
- if constexpr (std::is_copy_constructible_v<typename T::first_type> && std::is_copy_constructible_v<typename T::second_type>)
949
+ // Access methods
950
+ if constexpr (std::is_const_v<std::remove_reference_t<std::remove_pointer_t<typename T::first_type>>>)
619
951
  {
620
- klass_.define_method("copy", [](T& pair) -> T
621
- {
622
- return pair;
623
- });
952
+ klass_.define_attr("first", &T::first, Rice::AttrAccess::Read);
624
953
  }
625
954
  else
626
955
  {
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
- });
956
+ klass_.define_attr("first", &T::first, Rice::AttrAccess::ReadWrite);
632
957
  }
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
958
 
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&
959
+ if constexpr (std::is_const_v<std::remove_reference_t<std::remove_pointer_t<typename T::second_type>>>)
652
960
  {
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&
961
+ klass_.define_attr("second", &T::second, Rice::AttrAccess::Read);
962
+ }
963
+ else
664
964
  {
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
- });
965
+ klass_.define_attr("second", &T::second, Rice::AttrAccess::ReadWrite);
966
+ }
675
967
  }
676
968
 
677
969
  void define_to_s()
@@ -707,8 +999,8 @@ namespace Rice
707
999
 
708
1000
  if (klassName.empty())
709
1001
  {
710
- std::string typeName = detail::typeName(typeid(Pair_T));
711
- klassName = detail::rubyClassName(typeName);
1002
+ detail::TypeMapper<Pair_T> typeMapper;
1003
+ klassName = typeMapper.rubyName();
712
1004
  }
713
1005
 
714
1006
  Module rb_mStd = define_module("Std");
@@ -777,8 +1069,7 @@ namespace Rice
777
1069
  MapHelper(Data_Type<T> klass) : klass_(klass)
778
1070
  {
779
1071
  this->register_pair();
780
- this->define_constructor();
781
- this->define_copyable_methods();
1072
+ this->define_constructors();
782
1073
  this->define_capacity_methods();
783
1074
  this->define_access_methods();
784
1075
  this->define_comparable_methods();
@@ -795,27 +1086,13 @@ namespace Rice
795
1086
  define_pair<const Key_T, Mapped_T>();
796
1087
  }
797
1088
 
798
- void define_constructor()
1089
+ void define_constructors()
799
1090
  {
800
1091
  klass_.define_constructor(Constructor<T>());
801
- }
802
1092
 
803
- void define_copyable_methods()
804
- {
805
- if constexpr (std::is_copy_constructible_v<Value_T>)
1093
+ if constexpr (std::is_copy_constructible_v<Key_T> && std::is_copy_constructible_v<Value_T>)
806
1094
  {
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
- });
1095
+ klass_.define_constructor(Constructor<T, const T&>());
819
1096
  }
820
1097
  }
821
1098
 
@@ -998,8 +1275,8 @@ namespace Rice
998
1275
 
999
1276
  if (klassName.empty())
1000
1277
  {
1001
- std::string typeName = detail::typeName(typeid(Map_T));
1002
- klassName = detail::rubyClassName(typeName);
1278
+ detail::TypeMapper<Map_T> typeMapper;
1279
+ klassName = typeMapper.rubyName();
1003
1280
  }
1004
1281
 
1005
1282
  Module rb_mStd = define_module("Std");
@@ -1176,6 +1453,12 @@ namespace Rice
1176
1453
  class From_Ruby<std::map<T, U>*>
1177
1454
  {
1178
1455
  public:
1456
+ From_Ruby() = default;
1457
+
1458
+ explicit From_Ruby(Arg* arg) : arg_(arg)
1459
+ {
1460
+ }
1461
+
1179
1462
  Convertible is_convertible(VALUE value)
1180
1463
  {
1181
1464
  switch (rb_type(value))
@@ -1221,6 +1504,7 @@ namespace Rice
1221
1504
  }
1222
1505
 
1223
1506
  private:
1507
+ Arg* arg_;
1224
1508
  std::map<T, U> converted_;
1225
1509
  };
1226
1510
  }
@@ -1241,32 +1525,62 @@ namespace Rice::detail
1241
1525
  {
1242
1526
  return true;
1243
1527
  }
1528
+
1529
+ static VALUE rubyKlass()
1530
+ {
1531
+ return rb_cNilClass;
1532
+ }
1244
1533
  };
1245
1534
 
1246
1535
  template<>
1247
1536
  class To_Ruby<std::monostate>
1248
1537
  {
1249
1538
  public:
1539
+ To_Ruby() = default;
1540
+
1541
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
1542
+ {
1543
+ }
1544
+
1250
1545
  VALUE convert(const std::monostate& _)
1251
1546
  {
1252
1547
  return Qnil;
1253
1548
  }
1549
+
1550
+
1551
+ private:
1552
+ Return* returnInfo_ = nullptr;
1254
1553
  };
1255
1554
 
1256
1555
  template<>
1257
1556
  class To_Ruby<std::monostate&>
1258
1557
  {
1259
1558
  public:
1260
- static VALUE convert(const std::monostate& data, bool takeOwnership = false)
1559
+ To_Ruby() = default;
1560
+
1561
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
1562
+ {
1563
+ }
1564
+
1565
+ VALUE convert(const std::monostate& data)
1261
1566
  {
1262
1567
  return Qnil;
1263
1568
  }
1569
+
1570
+ private:
1571
+ Return* returnInfo_ = nullptr;
1264
1572
  };
1265
1573
 
1266
1574
  template<>
1267
1575
  class From_Ruby<std::monostate>
1268
1576
  {
1269
1577
  public:
1578
+ From_Ruby() = default;
1579
+
1580
+ explicit From_Ruby(Arg* arg)
1581
+ {
1582
+ }
1583
+
1270
1584
  Convertible is_convertible(VALUE value)
1271
1585
  {
1272
1586
  return value == Qnil ? Convertible::Exact : Convertible::None;
@@ -1289,6 +1603,12 @@ namespace Rice::detail
1289
1603
  class From_Ruby<std::monostate&>
1290
1604
  {
1291
1605
  public:
1606
+ From_Ruby() = default;
1607
+
1608
+ explicit From_Ruby(Arg* arg)
1609
+ {
1610
+ }
1611
+
1292
1612
  Convertible is_convertible(VALUE value)
1293
1613
  {
1294
1614
  return value == Qnil ? Convertible::Exact : Convertible::None;
@@ -1345,8 +1665,7 @@ namespace Rice
1345
1665
  MultimapHelper(Data_Type<T> klass) : klass_(klass)
1346
1666
  {
1347
1667
  this->register_pair();
1348
- this->define_constructor();
1349
- this->define_copyable_methods();
1668
+ this->define_constructors();
1350
1669
  this->define_capacity_methods();
1351
1670
  this->define_access_methods();
1352
1671
  this->define_comparable_methods();
@@ -1362,27 +1681,13 @@ namespace Rice
1362
1681
  define_pair<const Key_T, Mapped_T>();
1363
1682
  }
1364
1683
 
1365
- void define_constructor()
1684
+ void define_constructors()
1366
1685
  {
1367
1686
  klass_.define_constructor(Constructor<T>());
1368
- }
1369
1687
 
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
1688
+ if constexpr (std::is_copy_constructible_v<Key_T> && std::is_copy_constructible_v<Value_T>)
1380
1689
  {
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
- });
1690
+ klass_.define_constructor(Constructor<T, const T&>());
1386
1691
  }
1387
1692
  }
1388
1693
 
@@ -1400,14 +1705,14 @@ namespace Rice
1400
1705
  {
1401
1706
  // Access methods
1402
1707
  klass_.
1403
- define_method("[]", [](const T& multimap, const Key_T& key) -> Array
1708
+ define_method("[]", [](T& multimap, const Key_T& key) -> Array
1404
1709
  {
1405
1710
  Array result;
1406
1711
  auto range = multimap.equal_range(key);
1407
1712
 
1408
1713
  for (auto iter = range.first; iter != range.second; iter++)
1409
1714
  {
1410
- result.push<Mapped_T>(iter->second);
1715
+ result.push(iter->second, false);
1411
1716
  }
1412
1717
 
1413
1718
  return result;
@@ -1510,7 +1815,8 @@ namespace Rice
1510
1815
  auto iter = multimap.begin();
1511
1816
 
1512
1817
  std::stringstream stream;
1513
- stream << "<" << detail::rubyClassName(detail::typeName(typeid(T))) << ":";
1818
+ detail::TypeMapper<T> typeMapper;
1819
+ stream << "<" << typeMapper.rubyName() << ":";
1514
1820
  stream << "{";
1515
1821
 
1516
1822
  for (; iter != multimap.end(); iter++)
@@ -1548,8 +1854,8 @@ namespace Rice
1548
1854
 
1549
1855
  if (klassName.empty())
1550
1856
  {
1551
- std::string typeName = detail::typeName(typeid(MultiMap_T));
1552
- klassName = detail::rubyClassName(typeName);
1857
+ detail::TypeMapper<MultiMap_T> typeMapper;
1858
+ klassName = typeMapper.rubyName();
1553
1859
  }
1554
1860
 
1555
1861
  Module rb_mStd = define_module("Std");
@@ -1723,6 +2029,12 @@ namespace Rice
1723
2029
  class From_Ruby<std::multimap<T, U>*>
1724
2030
  {
1725
2031
  public:
2032
+ From_Ruby() = default;
2033
+
2034
+ explicit From_Ruby(Arg* arg) : arg_(arg)
2035
+ {
2036
+ }
2037
+
1726
2038
  Convertible is_convertible(VALUE value)
1727
2039
  {
1728
2040
  switch (rb_type(value))
@@ -1768,6 +2080,7 @@ namespace Rice
1768
2080
  }
1769
2081
 
1770
2082
  private:
2083
+ Arg* arg_;
1771
2084
  std::multimap<T, U> converted_;
1772
2085
  };
1773
2086
  }
@@ -1961,9 +2274,9 @@ namespace Rice
1961
2274
  klass_.define_method("to_a", [](T& self) -> VALUE
1962
2275
  {
1963
2276
  Array array;
1964
- for (const Value_T& element: self)
2277
+ for (auto element: self)
1965
2278
  {
1966
- array.push(element);
2279
+ array.push(element, false);
1967
2280
  }
1968
2281
 
1969
2282
  return array.value();
@@ -1980,7 +2293,8 @@ namespace Rice
1980
2293
  auto finish = self.end();
1981
2294
 
1982
2295
  std::stringstream stream;
1983
- stream << "<" << detail::rubyClassName(detail::typeName(typeid(T))) << ":";
2296
+ detail::TypeMapper<T> typeMapper;
2297
+ stream << "<" << typeMapper.rubyName() << ":";
1984
2298
  stream << "{";
1985
2299
 
1986
2300
  for (; iter != finish; iter++)
@@ -2021,8 +2335,8 @@ namespace Rice
2021
2335
 
2022
2336
  if (klassName.empty())
2023
2337
  {
2024
- std::string typeName = detail::typeName(typeid(Set_T));
2025
- klassName = detail::rubyClassName(typeName);
2338
+ detail::TypeMapper<Set_T> typeMapper;
2339
+ klassName = typeMapper.rubyName();
2026
2340
  }
2027
2341
 
2028
2342
  Module rb_mStd = define_module("Std");
@@ -2053,11 +2367,11 @@ namespace Rice
2053
2367
  return Qnil;
2054
2368
  };
2055
2369
 
2056
- using NativeFunction_T = NativeFunction<void, decltype(block), false>;
2370
+ using Proc_T = decltype(block);
2371
+ using NativeProc_T = NativeProc<Proc_T>;
2372
+ std::unique_ptr<NativeProc_T> proc(NativeProc_T::define(std::forward<Proc_T>(block)));
2057
2373
 
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);
2374
+ detail::protect<Function_T>(rb_block_call, rubySet, identifier.id(), 0, nullptr, NativeProc_T::resolve, (VALUE)proc.get());
2061
2375
 
2062
2376
  return result;
2063
2377
  }
@@ -2218,6 +2532,12 @@ namespace Rice
2218
2532
  private:
2219
2533
  static inline std::string setName = "Set";
2220
2534
  public:
2535
+ From_Ruby() = default;
2536
+
2537
+ explicit From_Ruby(Arg* arg) : arg_(arg)
2538
+ {
2539
+ }
2540
+
2221
2541
  Convertible is_convertible(VALUE value)
2222
2542
  {
2223
2543
  switch (rb_type(value))
@@ -2274,6 +2594,7 @@ namespace Rice
2274
2594
  }
2275
2595
 
2276
2596
  private:
2597
+ Arg* arg_;
2277
2598
  std::set<T> converted_;
2278
2599
  };
2279
2600
  }
@@ -2319,8 +2640,8 @@ namespace Rice
2319
2640
 
2320
2641
  if (klassName.empty())
2321
2642
  {
2322
- std::string typeName = detail::typeName(typeid(SharedPtr_T));
2323
- klassName = detail::rubyClassName(typeName);
2643
+ detail::TypeMapper<SharedPtr_T> typeMapper;
2644
+ klassName = typeMapper.rubyName();
2324
2645
  }
2325
2646
 
2326
2647
  Module rb_mStd = define_module("Std");
@@ -2373,7 +2694,29 @@ namespace Rice::detail
2373
2694
  {
2374
2695
  static bool verify()
2375
2696
  {
2376
- return Type<T>::verify();
2697
+ if constexpr (std::is_fundamental_v<T>)
2698
+ {
2699
+ return Type<Pointer<T>>::verify();
2700
+ return Type<Buffer<T>>::verify();
2701
+ }
2702
+ else
2703
+ {
2704
+ return Type<T>::verify();
2705
+ }
2706
+ }
2707
+
2708
+ static VALUE rubyKlass()
2709
+ {
2710
+ if (Data_Type<std::shared_ptr<T>>::is_defined())
2711
+ {
2712
+ std::pair<VALUE, rb_data_type_t*> pair = Registries::instance.types.getType<std::shared_ptr<T>>();
2713
+ return pair.first;
2714
+ }
2715
+ else
2716
+ {
2717
+ TypeMapper<T> typeMapper;
2718
+ return typeMapper.rubyKlass();
2719
+ }
2377
2720
  }
2378
2721
  };
2379
2722
 
@@ -2381,11 +2724,17 @@ namespace Rice::detail
2381
2724
  class To_Ruby<std::shared_ptr<T>>
2382
2725
  {
2383
2726
  public:
2727
+ To_Ruby() = default;
2728
+
2729
+ explicit To_Ruby(Arg* arv)
2730
+ {
2731
+ }
2732
+
2384
2733
  VALUE convert(std::shared_ptr<T>& data)
2385
2734
  {
2386
2735
  if constexpr (std::is_fundamental_v<T>)
2387
2736
  {
2388
- return detail::wrap(Data_Type<T>::klass(), Data_Type<T>::ruby_data_type(), data, true);
2737
+ return detail::wrap<std::shared_ptr<T>>(Data_Type<Pointer<T>>::klass(), Data_Type<Pointer<T>>::ruby_data_type(), data, true);
2389
2738
  }
2390
2739
  else
2391
2740
  {
@@ -2397,7 +2746,7 @@ namespace Rice::detail
2397
2746
  {
2398
2747
  if constexpr (std::is_fundamental_v<T>)
2399
2748
  {
2400
- return detail::wrap(Data_Type<T>::klass(), Data_Type<T>::ruby_data_type(), data, true);
2749
+ return detail::wrap<std::shared_ptr<T>>(Data_Type<Pointer<T>>::klass(), Data_Type<Pointer<T>>::ruby_data_type(), data, true);
2401
2750
  }
2402
2751
  else
2403
2752
  {
@@ -2442,10 +2791,10 @@ namespace Rice::detail
2442
2791
  std::shared_ptr<T>* ptr = unwrap<std::shared_ptr<T>>(value, Data_Type<std::shared_ptr<T>>::ruby_data_type(), false);
2443
2792
  return *ptr;
2444
2793
  }
2445
- else if constexpr (std::is_fundamental_v<T>)
2794
+ else if (std::is_fundamental_v<T>)
2446
2795
  {
2447
2796
  // 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());
2797
+ Wrapper<std::shared_ptr<T>>* wrapper = getWrapper<Wrapper<std::shared_ptr<T>>>(value, Data_Type<Pointer<T>>::ruby_data_type());
2449
2798
  return wrapper->data();
2450
2799
  }
2451
2800
  else
@@ -2463,16 +2812,15 @@ namespace Rice::detail
2463
2812
  class To_Ruby<std::shared_ptr<T>&>
2464
2813
  {
2465
2814
  public:
2815
+ To_Ruby() = default;
2816
+
2817
+ explicit To_Ruby(Arg* arg)
2818
+ {
2819
+ }
2820
+
2466
2821
  VALUE convert(std::shared_ptr<T>& data)
2467
2822
  {
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
- }
2823
+ return detail::wrap(Data_Type<T>::klass(), Data_Type<T>::ruby_data_type(), data, true);
2476
2824
  }
2477
2825
  };
2478
2826
 
@@ -2512,10 +2860,10 @@ namespace Rice::detail
2512
2860
  std::shared_ptr<T>* ptr = unwrap<std::shared_ptr<T>>(value, Data_Type<std::shared_ptr<T>>::ruby_data_type(), false);
2513
2861
  return *ptr;
2514
2862
  }
2515
- else if constexpr (std::is_fundamental_v<T>)
2863
+ else if (std::is_fundamental_v<T>)
2516
2864
  {
2517
2865
  // 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());
2866
+ Wrapper<std::shared_ptr<T>>* wrapper = getWrapper<Wrapper<std::shared_ptr<T>>>(value, Data_Type<Pointer<T>>::ruby_data_type());
2519
2867
  return wrapper->data();
2520
2868
  }
2521
2869
  else
@@ -2557,42 +2905,65 @@ namespace Rice::detail
2557
2905
  auto indices = std::make_index_sequence<std::tuple_size_v<std::tuple<Types...>>>{};
2558
2906
  return verifyTypes(indices);
2559
2907
  }
2908
+
2909
+ static VALUE rubyKlass()
2910
+ {
2911
+ return rb_cArray;
2912
+ }
2560
2913
  };
2561
2914
 
2562
2915
  template<typename...Types>
2563
2916
  class To_Ruby<std::tuple<Types...>>
2564
2917
  {
2565
2918
  public:
2566
- static VALUE convert(const std::tuple<Types...>& data, bool takeOwnership = false)
2919
+ To_Ruby() = default;
2920
+
2921
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
2922
+ {
2923
+ }
2924
+
2925
+ VALUE convert(const std::tuple<Types...>& data)
2567
2926
  {
2568
2927
  Array result;
2569
2928
 
2570
2929
  for_each_tuple(data, [&](auto element)
2571
2930
  {
2572
- using Element_T = decltype(element);
2573
- result.push<Element_T>((Element_T)element);
2931
+ result.push(element, true);
2574
2932
  });
2575
2933
 
2576
2934
  return result.value();
2577
2935
  }
2936
+
2937
+ private:
2938
+ Return* returnInfo_ = nullptr;
2578
2939
  };
2579
2940
 
2580
2941
  template<typename...Types>
2581
2942
  class To_Ruby<std::tuple<Types...>&>
2582
2943
  {
2583
2944
  public:
2584
- static VALUE convert(const std::tuple<Types...>& data, bool takeOwnership = false)
2945
+ To_Ruby() = default;
2946
+
2947
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
2948
+ {
2949
+ }
2950
+
2951
+ VALUE convert(const std::tuple<Types...>& data)
2585
2952
  {
2586
2953
  Array result;
2587
2954
 
2588
- for_each_tuple(data, [&](auto& value)
2589
- {
2590
- VALUE element = detail::To_Ruby<decltype(value)>().convert(value);
2591
- result.push(element);
2592
- });
2955
+ bool isOwner = (this->returnInfo_ && this->returnInfo_->isOwner());
2956
+
2957
+ for_each_tuple(data, [&](auto& element)
2958
+ {
2959
+ result.push(element, isOwner);
2960
+ });
2593
2961
 
2594
2962
  return result.value();
2595
2963
  }
2964
+
2965
+ private:
2966
+ Return* returnInfo_ = nullptr;
2596
2967
  };
2597
2968
 
2598
2969
  template<typename...Types>
@@ -2607,6 +2978,12 @@ namespace Rice::detail
2607
2978
  return (Type<std::tuple_element_t<I, Tuple_T>>::verify() && ...);
2608
2979
  }
2609
2980
 
2981
+ From_Ruby() = default;
2982
+
2983
+ explicit From_Ruby(Arg* arg)
2984
+ {
2985
+ }
2986
+
2610
2987
  Convertible is_convertible(VALUE value)
2611
2988
  {
2612
2989
  Convertible result = Convertible::None;
@@ -2756,27 +3133,37 @@ namespace Rice::detail
2756
3133
  return (Type<std::tuple_element_t<I, Tuple_T>>::verify() && ...);
2757
3134
  }
2758
3135
 
2759
- template<std::size_t... I>
2760
3136
  constexpr static bool verify()
2761
3137
  {
2762
3138
  auto indices = std::make_index_sequence<std::variant_size_v<std::variant<Types...>>>{};
2763
3139
  return verifyTypes(indices);
2764
3140
  }
3141
+
3142
+ static VALUE rubyKlass()
3143
+ {
3144
+ // There is no direct mapping to Ruby, so just return Object
3145
+ return rb_cObject;
3146
+ }
2765
3147
  };
2766
3148
 
2767
3149
  template<typename...Types>
2768
3150
  class To_Ruby<std::variant<Types...>>
2769
3151
  {
2770
3152
  public:
3153
+ To_Ruby() = default;
3154
+
3155
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
3156
+ {
3157
+ }
2771
3158
 
2772
3159
  template<typename U, typename V>
2773
- static VALUE convertElement(U& data, bool takeOwnership)
3160
+ VALUE convertElement(U& data, bool takeOwnership)
2774
3161
  {
2775
3162
  return To_Ruby<V>().convert(std::forward<V>(std::get<V>(data)));
2776
3163
  }
2777
3164
 
2778
3165
  template<typename U, std::size_t... I>
2779
- static VALUE convertIterator(U& data, bool takeOwnership, std::index_sequence<I...>& indices)
3166
+ VALUE convertIterator(U& data, bool takeOwnership, std::index_sequence<I...>& indices)
2780
3167
  {
2781
3168
  // Create a tuple of the variant types so we can look over the tuple's types
2782
3169
  using Tuple_T = std::tuple<Types...>;
@@ -2819,26 +3206,36 @@ namespace Rice::detail
2819
3206
  }
2820
3207
 
2821
3208
  template<typename U>
2822
- static VALUE convert(U& data, bool takeOwnership = false)
3209
+ VALUE convert(U& data)
2823
3210
  {
2824
3211
  auto indices = std::make_index_sequence<std::variant_size_v<std::variant<Types...>>>{};
2825
- return convertIterator(data, takeOwnership, indices);
3212
+ return convertIterator(data, true, indices);
2826
3213
  }
2827
3214
 
2828
3215
  template<typename U>
2829
- static VALUE convert(U&& data, bool takeOwnership = false)
3216
+ VALUE convert(U&& data)
2830
3217
  {
3218
+ bool isOwner = true;
2831
3219
  auto indices = std::make_index_sequence<std::variant_size_v<std::variant<Types...>>>{};
2832
- return convertIterator(data, takeOwnership, indices);
3220
+ return convertIterator(data, isOwner, indices);
2833
3221
  }
3222
+
3223
+ private:
3224
+ Return* returnInfo_ = nullptr;
2834
3225
  };
2835
3226
 
2836
3227
  template<typename...Types>
2837
3228
  class To_Ruby<std::variant<Types...>&>
2838
3229
  {
2839
3230
  public:
3231
+ To_Ruby() = default;
3232
+
3233
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
3234
+ {
3235
+ }
3236
+
2840
3237
  template<typename U, typename V>
2841
- static VALUE convertElement(U& data, bool takeOwnership)
3238
+ VALUE convertElement(U& data, bool takeOwnership)
2842
3239
  {
2843
3240
  if constexpr (std::is_const_v<U>)
2844
3241
  {
@@ -2851,7 +3248,7 @@ namespace Rice::detail
2851
3248
  }
2852
3249
 
2853
3250
  template<typename U, std::size_t... I>
2854
- static VALUE convertIterator(U& data, bool takeOwnership, std::index_sequence<I...>& indices)
3251
+ VALUE convertIterator(U& data, bool takeOwnership, std::index_sequence<I...>& indices)
2855
3252
  {
2856
3253
  // Create a tuple of the variant types so we can look over the tuple's types
2857
3254
  using Tuple_T = std::tuple<Types...>;
@@ -2875,17 +3272,27 @@ namespace Rice::detail
2875
3272
  }
2876
3273
 
2877
3274
  template<typename U>
2878
- static VALUE convert(U& data, bool takeOwnership = false)
3275
+ VALUE convert(U& data)
2879
3276
  {
3277
+ bool isOwner = (this->returnInfo_ && this->returnInfo_->isOwner());
2880
3278
  auto indices = std::make_index_sequence<std::variant_size_v<std::variant<Types...>>>{};
2881
- return convertIterator(data, takeOwnership, indices);
3279
+ return convertIterator(data, isOwner, indices);
2882
3280
  }
3281
+
3282
+ private:
3283
+ Return* returnInfo_ = nullptr;
2883
3284
  };
2884
3285
 
2885
3286
  template<typename...Types>
2886
3287
  class From_Ruby<std::variant<Types...>>
2887
3288
  {
2888
3289
  public:
3290
+ From_Ruby() = default;
3291
+
3292
+ explicit From_Ruby(Arg* arg)
3293
+ {
3294
+ }
3295
+
2889
3296
  Convertible is_convertible(VALUE value)
2890
3297
  {
2891
3298
  Convertible result = Convertible::None;
@@ -2972,6 +3379,12 @@ namespace Rice::detail
2972
3379
  class From_Ruby<std::variant<Types...>&> : public From_Ruby<std::variant<Types...>>
2973
3380
  {
2974
3381
  public:
3382
+ From_Ruby() = default;
3383
+
3384
+ explicit From_Ruby(Arg* arg)
3385
+ {
3386
+ }
3387
+
2975
3388
  std::variant<Types...>& convert(VALUE value)
2976
3389
  {
2977
3390
  int index = this->figureIndex(value);
@@ -3037,6 +3450,12 @@ namespace Rice::detail
3037
3450
  class To_Ruby<std::unique_ptr<T>>
3038
3451
  {
3039
3452
  public:
3453
+ To_Ruby() = default;
3454
+
3455
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
3456
+ {
3457
+ }
3458
+
3040
3459
  VALUE convert(std::unique_ptr<T>& data)
3041
3460
  {
3042
3461
  std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(*data);
@@ -3048,17 +3467,29 @@ namespace Rice::detail
3048
3467
  std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(*data);
3049
3468
  return detail::wrap<std::unique_ptr<T>>(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
3050
3469
  }
3470
+
3471
+ private:
3472
+ Return* returnInfo_ = nullptr;
3051
3473
  };
3052
3474
 
3053
3475
  template <typename T>
3054
3476
  class To_Ruby<std::unique_ptr<T>&>
3055
3477
  {
3056
3478
  public:
3479
+ To_Ruby() = default;
3480
+
3481
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
3482
+ {
3483
+ }
3484
+
3057
3485
  VALUE convert(std::unique_ptr<T>& data)
3058
3486
  {
3059
3487
  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);
3488
+ return detail::wrap<std::unique_ptr<T>>(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
3061
3489
  }
3490
+
3491
+ private:
3492
+ Return* returnInfo_ = nullptr;
3062
3493
  };
3063
3494
 
3064
3495
  template <typename T>
@@ -3071,6 +3502,12 @@ namespace Rice::detail
3071
3502
  return dynamic_cast<Wrapper<std::unique_ptr<T>>*>(wrapper);
3072
3503
  }
3073
3504
 
3505
+ From_Ruby() = default;
3506
+
3507
+ explicit From_Ruby(Arg* arg)
3508
+ {
3509
+ }
3510
+
3074
3511
  Convertible is_convertible(VALUE value)
3075
3512
  {
3076
3513
  if (!is_same_smart_ptr(value))
@@ -3108,6 +3545,12 @@ namespace Rice::detail
3108
3545
  return dynamic_cast<Wrapper<std::unique_ptr<T>>*>(wrapper);
3109
3546
  }
3110
3547
 
3548
+ From_Ruby() = default;
3549
+
3550
+ explicit From_Ruby(Arg* arg)
3551
+ {
3552
+ }
3553
+
3111
3554
  Convertible is_convertible(VALUE value)
3112
3555
  {
3113
3556
  if (!is_same_smart_ptr(value))
@@ -3140,7 +3583,21 @@ namespace Rice::detail
3140
3583
  {
3141
3584
  static bool verify()
3142
3585
  {
3143
- return Type<T>::verify();
3586
+ if constexpr (std::is_fundamental_v<T>)
3587
+ {
3588
+ return Type<Pointer<T>>::verify();
3589
+ return Type<Buffer<T>>::verify();
3590
+ }
3591
+ else
3592
+ {
3593
+ return Type<T>::verify();
3594
+ }
3595
+ }
3596
+
3597
+ static VALUE rubyKlass()
3598
+ {
3599
+ TypeMapper<T> typeMapper;
3600
+ return typeMapper.rubyKlass();
3144
3601
  }
3145
3602
  };
3146
3603
  }
@@ -3177,8 +3634,7 @@ namespace Rice
3177
3634
  UnorderedMapHelper(Data_Type<T> klass) : klass_(klass)
3178
3635
  {
3179
3636
  this->register_pair();
3180
- this->define_constructor();
3181
- this->define_copyable_methods();
3637
+ this->define_constructors();
3182
3638
  this->define_capacity_methods();
3183
3639
  this->define_access_methods();
3184
3640
  this->define_comparable_methods();
@@ -3195,27 +3651,13 @@ namespace Rice
3195
3651
  define_pair<const Key_T, T>();
3196
3652
  }
3197
3653
 
3198
- void define_constructor()
3654
+ void define_constructors()
3199
3655
  {
3200
3656
  klass_.define_constructor(Constructor<T>());
3201
- }
3202
3657
 
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
3658
+ if constexpr (std::is_copy_constructible_v<Key_T> && std::is_copy_constructible_v<Value_T>)
3213
3659
  {
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
- });
3660
+ klass_.define_constructor(Constructor<T, const T&>());
3219
3661
  }
3220
3662
  }
3221
3663
 
@@ -3398,8 +3840,8 @@ namespace Rice
3398
3840
 
3399
3841
  if (klassName.empty())
3400
3842
  {
3401
- std::string typeName = detail::typeName(typeid(UnorderedMap_T));
3402
- klassName = detail::rubyClassName(typeName);
3843
+ detail::TypeMapper<UnorderedMap_T> typeMapper;
3844
+ klassName = typeMapper.rubyName();
3403
3845
  }
3404
3846
 
3405
3847
  Module rb_mStd = define_module("Std");
@@ -3576,6 +4018,12 @@ namespace Rice
3576
4018
  class From_Ruby<std::unordered_map<T, U>*>
3577
4019
  {
3578
4020
  public:
4021
+ From_Ruby() = default;
4022
+
4023
+ explicit From_Ruby(Arg* arg) : arg_(arg)
4024
+ {
4025
+ }
4026
+
3579
4027
  Convertible is_convertible(VALUE value)
3580
4028
  {
3581
4029
  switch (rb_type(value))
@@ -3621,6 +4069,7 @@ namespace Rice
3621
4069
  }
3622
4070
 
3623
4071
  private:
4072
+ Arg* arg_;
3624
4073
  std::unordered_map<T, U> converted_;
3625
4074
  };
3626
4075
  }
@@ -3676,12 +4125,10 @@ namespace Rice
3676
4125
  // Helper method to translate Ruby indices to vector indices
3677
4126
  Difference_T normalizeIndex(Size_T size, Difference_T index, bool enforceBounds = false)
3678
4127
  {
3679
- // Negative indices mean count from the right. Note that negative indices
3680
- // wrap around!
3681
- if (index < 0)
4128
+ // Negative indices mean count from the right
4129
+ if (index < 0 && (-index <= size))
3682
4130
  {
3683
- index = ((-index) % size);
3684
- index = index > 0 ? size - index : index;
4131
+ index = size + index;
3685
4132
  }
3686
4133
 
3687
4134
  if (enforceBounds && (index < 0 || index >= (Difference_T)size))
@@ -3694,9 +4141,13 @@ namespace Rice
3694
4141
 
3695
4142
  void define_constructors()
3696
4143
  {
3697
- klass_.define_constructor(Constructor<T>())
3698
- .define_constructor(Constructor<T, Size_T, const Parameter_T>())
3699
- .define_constructor(Constructor<T, const T&>());
4144
+ klass_.define_constructor(Constructor<T>());
4145
+
4146
+ if constexpr (std::is_copy_constructible_v<Value_T>)
4147
+ {
4148
+ klass_.define_constructor(Constructor<T, const T&>())
4149
+ .define_constructor(Constructor<T, Size_T, const Parameter_T>());
4150
+ }
3700
4151
 
3701
4152
  if constexpr (std::is_default_constructible_v<Value_T>)
3702
4153
  {
@@ -3758,42 +4209,85 @@ namespace Rice
3758
4209
 
3759
4210
  void define_access_methods()
3760
4211
  {
3761
- // Access methods
3762
- klass_.define_method("first", [](const T& vector) -> std::optional<Value_T>
4212
+ if constexpr (!std::is_same_v<Value_T, bool>)
3763
4213
  {
3764
- if (vector.size() > 0)
3765
- {
3766
- return vector.front();
3767
- }
3768
- else
4214
+ // Access methods
4215
+ klass_.define_method("first", [](T& vector) -> std::optional<std::reference_wrapper<Value_T>>
3769
4216
  {
3770
- return std::nullopt;
3771
- }
3772
- })
3773
- .define_method("last", [](const T& vector) -> std::optional<Value_T>
3774
- {
3775
- if (vector.size() > 0)
4217
+ if (vector.size() > 0)
4218
+ {
4219
+ return vector.front();
4220
+ }
4221
+ else
4222
+ {
4223
+ return std::nullopt;
4224
+ }
4225
+ })
4226
+ .define_method("last", [](T& vector) -> std::optional<std::reference_wrapper<Value_T>>
3776
4227
  {
3777
- return vector.back();
3778
- }
3779
- else
4228
+ if (vector.size() > 0)
4229
+ {
4230
+ return vector.back();
4231
+ }
4232
+ else
4233
+ {
4234
+ return std::nullopt;
4235
+ }
4236
+ })
4237
+ .define_method("[]", [this](T& vector, Difference_T index) -> std::optional<std::reference_wrapper<Value_T>>
3780
4238
  {
3781
- return std::nullopt;
3782
- }
3783
- })
3784
- .define_method("[]", [this](const T& vector, Difference_T index) -> std::optional<Value_T>
4239
+ index = normalizeIndex(vector.size(), index);
4240
+ if (index < 0 || index >= (Difference_T)vector.size())
4241
+ {
4242
+ return std::nullopt;
4243
+ }
4244
+ else
4245
+ {
4246
+ return vector[index];
4247
+ }
4248
+ })
4249
+ .template define_method<Value_T*(T::*)()>("data", &T::data, Return().setBuffer());
4250
+ }
4251
+ else
3785
4252
  {
3786
- index = normalizeIndex(vector.size(), index);
3787
- if (index < 0 || index >= (Difference_T)vector.size())
4253
+ // Access methods
4254
+ klass_.define_method("first", [](T& vector) -> std::optional<Value_T>
3788
4255
  {
3789
- return std::nullopt;
3790
- }
3791
- else
4256
+ if (vector.size() > 0)
4257
+ {
4258
+ return vector.front();
4259
+ }
4260
+ else
4261
+ {
4262
+ return std::nullopt;
4263
+ }
4264
+ })
4265
+ .define_method("last", [](T& vector) -> std::optional<Value_T>
3792
4266
  {
3793
- return vector[index];
3794
- }
3795
- })
3796
- .define_method("[]", [this](const T& vector, Difference_T start, Difference_T length) -> VALUE
4267
+ if (vector.size() > 0)
4268
+ {
4269
+ return vector.back();
4270
+ }
4271
+ else
4272
+ {
4273
+ return std::nullopt;
4274
+ }
4275
+ })
4276
+ .define_method("[]", [this](T& vector, Difference_T index) -> std::optional<Value_T>
4277
+ {
4278
+ index = normalizeIndex(vector.size(), index);
4279
+ if (index < 0 || index >= (Difference_T)vector.size())
4280
+ {
4281
+ return std::nullopt;
4282
+ }
4283
+ else
4284
+ {
4285
+ return vector[index];
4286
+ }
4287
+ });
4288
+ }
4289
+
4290
+ klass_.define_method("[]", [this](T& vector, Difference_T start, Difference_T length) -> VALUE
3797
4291
  {
3798
4292
  start = normalizeIndex(vector.size(), start);
3799
4293
  if (start < 0 || start >= (Difference_T)vector.size())
@@ -3812,25 +4306,19 @@ namespace Rice
3812
4306
  }
3813
4307
 
3814
4308
  auto finish = vector.begin() + start + length;
3815
- T slice(begin, finish);
3816
4309
 
3817
4310
  VALUE result = rb_ary_new();
3818
- std::for_each(slice.begin(), slice.end(), [&result](const Reference_T element)
4311
+ for (auto iter = begin; iter != finish; iter++)
3819
4312
  {
3820
- VALUE value = detail::To_Ruby<Parameter_T>().convert(element);
4313
+ const Reference_T element = *iter;
4314
+ VALUE value = detail::To_Ruby<Reference_T>().convert(element);
3821
4315
  rb_ary_push(result, value);
3822
- });
4316
+ }
3823
4317
 
3824
4318
  return result;
3825
4319
  }
3826
4320
  }, Return().setValue());
3827
4321
 
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
4322
  rb_define_alias(klass_, "at", "[]");
3835
4323
  }
3836
4324
 
@@ -3840,35 +4328,39 @@ namespace Rice
3840
4328
  if constexpr (detail::is_comparable_v<T>)
3841
4329
  {
3842
4330
  klass_.define_method("delete", [](T& vector, Parameter_T element) -> std::optional<Value_T>
4331
+ {
4332
+ auto iter = std::find(vector.begin(), vector.end(), element);
4333
+ if (iter == vector.end())
3843
4334
  {
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)
4335
+ return std::nullopt;
4336
+ }
4337
+ else if constexpr (std::is_copy_assignable_v<Value_T>)
3857
4338
  {
3858
- return std::find(vector.begin(), vector.end(), element) != vector.end();
3859
- })
4339
+ Value_T result = *iter;
4340
+ vector.erase(iter);
4341
+ return result;
4342
+ }
4343
+ else
4344
+ {
4345
+ return std::nullopt;
4346
+ }
4347
+ })
4348
+ .define_method("include?", [](T& vector, Parameter_T element)
4349
+ {
4350
+ return std::find(vector.begin(), vector.end(), element) != vector.end();
4351
+ })
3860
4352
  .define_method("index", [](T& vector, Parameter_T element) -> std::optional<Difference_T>
4353
+ {
4354
+ auto iter = std::find(vector.begin(), vector.end(), element);
4355
+ if (iter == vector.end())
3861
4356
  {
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
- });
4357
+ return std::nullopt;
4358
+ }
4359
+ else
4360
+ {
4361
+ return iter - vector.begin();
4362
+ }
4363
+ });
3872
4364
  }
3873
4365
  else
3874
4366
  {
@@ -3890,45 +4382,65 @@ namespace Rice
3890
4382
  void define_modify_methods()
3891
4383
  {
3892
4384
  klass_.define_method("clear", &T::clear)
3893
- .define_method("delete_at", [](T& vector, const size_t& pos)
4385
+ .define_method("delete_at", [](T& vector, const size_t& pos) -> std::optional<Value_T>
4386
+ {
4387
+ auto iter = vector.begin() + pos;
4388
+
4389
+ if constexpr (std::is_copy_assignable_v<Value_T>)
3894
4390
  {
3895
- auto iter = vector.begin() + pos;
3896
4391
  Value_T result = *iter;
3897
4392
  vector.erase(iter);
3898
4393
  return result;
3899
- })
4394
+ }
4395
+ else
4396
+ {
4397
+ vector.erase(iter);
4398
+ return std::nullopt;
4399
+ }
4400
+ })
3900
4401
  .define_method("insert", [this](T& vector, Difference_T index, Parameter_T element) -> T&
4402
+ {
4403
+ int normalized = normalizeIndex(vector.size(), index, true);
4404
+ // For a Ruby array a positive index means insert the element before the index. But
4405
+ // a negative index means insert the element *after* the index. std::vector
4406
+ // inserts *before* the index. So add 1 if this is a negative index.
4407
+ if (index < 0)
3901
4408
  {
3902
- index = normalizeIndex(vector.size(), index, true);
3903
- auto iter = vector.begin() + index;
3904
- vector.insert(iter, element);
3905
- return vector;
3906
- })
4409
+ normalized++;
4410
+ }
4411
+ auto iter = vector.begin() + normalized;
4412
+ vector.insert(iter, std::move(element));
4413
+ return vector;
4414
+ })
3907
4415
  .define_method("pop", [](T& vector) -> std::optional<Value_T>
4416
+ {
4417
+ if constexpr (!std::is_copy_assignable_v<Value_T>)
3908
4418
  {
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&
4419
+ vector.pop_back();
4420
+ return std::nullopt;
4421
+ }
4422
+ else if (vector.empty())
3921
4423
  {
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
4424
+ return std::nullopt;
4425
+ }
4426
+ else
3927
4427
  {
3928
- index = normalizeIndex(vector.size(), index, true);
3929
- vector[index] = element;
3930
- return element;
3931
- });
4428
+ Value_T result = vector.back();
4429
+ vector.pop_back();
4430
+ return result;
4431
+ }
4432
+ })
4433
+ .define_method("push", [](T& vector, Parameter_T element) -> T&
4434
+ {
4435
+ vector.push_back(std::move(element));
4436
+ return vector;
4437
+ })
4438
+ .define_method("shrink_to_fit", &T::shrink_to_fit)
4439
+ .define_method("[]=", [this](T& vector, Difference_T index, Parameter_T element) -> void
4440
+ {
4441
+ index = normalizeIndex(vector.size(), index, true);
4442
+ vector[index] = std::move(element);
4443
+ });
3932
4444
 
3933
4445
  rb_define_alias(klass_, "push_back", "push");
3934
4446
  rb_define_alias(klass_, "<<", "push");
@@ -3949,7 +4461,7 @@ namespace Rice
3949
4461
  VALUE result = rb_ary_new();
3950
4462
  std::for_each(vector.begin(), vector.end(), [&result](const Reference_T element)
3951
4463
  {
3952
- VALUE value = detail::To_Ruby<Parameter_T>().convert(element);
4464
+ VALUE value = detail::To_Ruby<Reference_T>().convert(element);
3953
4465
  rb_ary_push(result, value);
3954
4466
  });
3955
4467
 
@@ -4007,8 +4519,8 @@ namespace Rice
4007
4519
 
4008
4520
  if (klassName.empty())
4009
4521
  {
4010
- std::string typeName = detail::typeName(typeid(Vector_T));
4011
- klassName = detail::rubyClassName(typeName);
4522
+ detail::TypeMapper<Vector_T> typeMapper;
4523
+ klassName = typeMapper.rubyName();
4012
4524
  }
4013
4525
 
4014
4526
  Module rb_mStd = define_module("Std");
@@ -4160,6 +4672,12 @@ namespace Rice
4160
4672
  class From_Ruby<std::vector<T>*>
4161
4673
  {
4162
4674
  public:
4675
+ From_Ruby() = default;
4676
+
4677
+ explicit From_Ruby(Arg* arg) : arg_(arg)
4678
+ {
4679
+ }
4680
+
4163
4681
  Convertible is_convertible(VALUE value)
4164
4682
  {
4165
4683
  switch (rb_type(value))
@@ -4207,6 +4725,7 @@ namespace Rice
4207
4725
  }
4208
4726
 
4209
4727
  private:
4728
+ Arg* arg_;
4210
4729
  std::vector<T> converted_;
4211
4730
  };
4212
4731
  }
@@ -4218,10 +4737,19 @@ namespace Rice
4218
4737
  class To_Ruby<std::vector<bool>::reference>
4219
4738
  {
4220
4739
  public:
4740
+ To_Ruby() = default;
4741
+
4742
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
4743
+ {
4744
+ }
4745
+
4221
4746
  VALUE convert(const std::vector<bool>::reference& value)
4222
4747
  {
4223
4748
  return value ? Qtrue : Qfalse;
4224
4749
  }
4750
+
4751
+ private:
4752
+ Return* returnInfo_ = nullptr;
4225
4753
  };
4226
4754
  }
4227
4755
  }