rice 3.0.0 → 4.0.3

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 (238) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +121 -0
  3. data/CONTRIBUTORS.md +19 -0
  4. data/Gemfile +3 -0
  5. data/README.md +44 -1025
  6. data/Rakefile +95 -12
  7. data/include/rice/rice.hpp +7766 -0
  8. data/include/rice/stl.hpp +1113 -0
  9. data/lib/mkmf-rice.rb +127 -0
  10. data/lib/version.rb +3 -0
  11. data/rice/Address_Registration_Guard.ipp +75 -32
  12. data/rice/Address_Registration_Guard_defn.hpp +60 -56
  13. data/rice/Arg.hpp +80 -4
  14. data/rice/Arg.ipp +51 -0
  15. data/rice/Constructor.hpp +12 -14
  16. data/rice/Data_Object.ipp +234 -107
  17. data/rice/Data_Object_defn.hpp +77 -117
  18. data/rice/Data_Type.hpp +1 -2
  19. data/rice/Data_Type.ipp +251 -295
  20. data/rice/Data_Type_defn.hpp +175 -243
  21. data/rice/Director.hpp +11 -6
  22. data/rice/Enum.hpp +54 -104
  23. data/rice/Enum.ipp +104 -230
  24. data/rice/Exception.hpp +2 -8
  25. data/rice/Exception.ipp +65 -0
  26. data/rice/Exception_defn.hpp +46 -47
  27. data/rice/Identifier.hpp +28 -28
  28. data/rice/Identifier.ipp +23 -27
  29. data/rice/Return.hpp +39 -0
  30. data/rice/Return.ipp +33 -0
  31. data/rice/detail/Exception_Handler.ipp +22 -62
  32. data/rice/detail/Exception_Handler_defn.hpp +76 -91
  33. data/rice/detail/Iterator.hpp +18 -88
  34. data/rice/detail/Iterator.ipp +47 -0
  35. data/rice/detail/Jump_Tag.hpp +21 -0
  36. data/rice/detail/MethodInfo.hpp +44 -0
  37. data/rice/detail/MethodInfo.ipp +78 -0
  38. data/rice/detail/NativeAttribute.hpp +53 -0
  39. data/rice/detail/NativeAttribute.ipp +83 -0
  40. data/rice/detail/NativeFunction.hpp +69 -0
  41. data/rice/detail/NativeFunction.ipp +248 -0
  42. data/rice/detail/RubyFunction.hpp +39 -0
  43. data/rice/detail/RubyFunction.ipp +92 -0
  44. data/rice/detail/Type.hpp +29 -0
  45. data/rice/detail/Type.ipp +138 -0
  46. data/rice/detail/TypeRegistry.hpp +50 -0
  47. data/rice/detail/TypeRegistry.ipp +106 -0
  48. data/rice/detail/Wrapper.hpp +51 -0
  49. data/rice/detail/Wrapper.ipp +151 -0
  50. data/rice/detail/default_allocation_func.hpp +8 -19
  51. data/rice/detail/default_allocation_func.ipp +9 -8
  52. data/rice/detail/from_ruby.hpp +2 -37
  53. data/rice/detail/from_ruby.ipp +1020 -46
  54. data/rice/detail/from_ruby_defn.hpp +38 -0
  55. data/rice/detail/function_traits.hpp +124 -0
  56. data/rice/detail/method_data.hpp +23 -15
  57. data/rice/detail/method_data.ipp +53 -0
  58. data/rice/detail/rice_traits.hpp +116 -0
  59. data/rice/detail/ruby.hpp +9 -46
  60. data/rice/detail/to_ruby.hpp +3 -17
  61. data/rice/detail/to_ruby.ipp +409 -31
  62. data/rice/detail/to_ruby_defn.hpp +48 -0
  63. data/rice/forward_declares.ipp +82 -0
  64. data/rice/global_function.hpp +16 -20
  65. data/rice/global_function.ipp +8 -17
  66. data/rice/rice.hpp +59 -0
  67. data/rice/ruby_mark.hpp +5 -3
  68. data/rice/ruby_try_catch.hpp +4 -4
  69. data/rice/stl.hpp +11 -0
  70. data/sample/callbacks/extconf.rb +3 -0
  71. data/sample/callbacks/sample_callbacks.cpp +10 -13
  72. data/sample/enum/extconf.rb +3 -0
  73. data/sample/enum/sample_enum.cpp +3 -17
  74. data/sample/enum/test.rb +2 -2
  75. data/sample/inheritance/animals.cpp +8 -24
  76. data/sample/inheritance/extconf.rb +3 -0
  77. data/sample/inheritance/test.rb +1 -1
  78. data/sample/map/extconf.rb +3 -0
  79. data/sample/map/map.cpp +10 -18
  80. data/sample/map/test.rb +1 -1
  81. data/test/embed_ruby.cpp +18 -5
  82. data/test/ext/t1/extconf.rb +3 -0
  83. data/test/ext/t1/t1.cpp +1 -3
  84. data/test/ext/t2/extconf.rb +3 -0
  85. data/test/ext/t2/t2.cpp +1 -1
  86. data/test/extconf.rb +23 -0
  87. data/test/ruby/test_callbacks_sample.rb +28 -0
  88. data/test/ruby/test_multiple_extensions.rb +18 -0
  89. data/test/ruby/test_multiple_extensions_same_class.rb +14 -0
  90. data/test/ruby/test_multiple_extensions_with_inheritance.rb +20 -0
  91. data/test/test_Address_Registration_Guard.cpp +23 -10
  92. data/test/test_Array.cpp +129 -73
  93. data/test/test_Attribute.cpp +147 -0
  94. data/test/test_Builtin_Object.cpp +34 -14
  95. data/test/test_Class.cpp +149 -275
  96. data/test/test_Constructor.cpp +10 -9
  97. data/test/test_Data_Object.cpp +133 -192
  98. data/test/test_Data_Type.cpp +322 -252
  99. data/test/test_Director.cpp +54 -41
  100. data/test/test_Enum.cpp +228 -103
  101. data/test/test_Exception.cpp +5 -6
  102. data/test/test_Hash.cpp +31 -30
  103. data/test/test_Identifier.cpp +4 -5
  104. data/test/test_Inheritance.cpp +221 -0
  105. data/test/test_Iterator.cpp +161 -0
  106. data/test/test_Jump_Tag.cpp +1 -1
  107. data/test/test_Keep_Alive.cpp +161 -0
  108. data/test/test_Memory_Management.cpp +2 -4
  109. data/test/test_Module.cpp +167 -110
  110. data/test/test_Object.cpp +41 -21
  111. data/test/test_Ownership.cpp +275 -0
  112. data/test/test_Self.cpp +205 -0
  113. data/test/test_Stl_Optional.cpp +90 -0
  114. data/test/test_Stl_Pair.cpp +144 -0
  115. data/test/test_Stl_SmartPointer.cpp +200 -0
  116. data/test/test_Stl_String.cpp +74 -0
  117. data/test/test_Stl_Vector.cpp +652 -0
  118. data/test/test_String.cpp +1 -2
  119. data/test/test_Struct.cpp +29 -39
  120. data/test/test_Symbol.cpp +1 -2
  121. data/test/test_To_From_Ruby.cpp +249 -285
  122. data/test/test_global_functions.cpp +39 -19
  123. data/test/unittest.hpp +0 -4
  124. metadata +70 -141
  125. data/Doxyfile +0 -2268
  126. data/Makefile.am +0 -26
  127. data/Makefile.in +0 -931
  128. data/README.mingw +0 -8
  129. data/aclocal.m4 +0 -1085
  130. data/ax_cxx_compile_stdcxx.m4 +0 -951
  131. data/bootstrap +0 -8
  132. data/config.guess +0 -1421
  133. data/config.sub +0 -1807
  134. data/configure +0 -7792
  135. data/configure.ac +0 -55
  136. data/depcomp +0 -791
  137. data/doxygen.ac +0 -314
  138. data/doxygen.am +0 -186
  139. data/extconf.rb +0 -70
  140. data/install-sh +0 -501
  141. data/missing +0 -215
  142. data/post-autoconf.rb +0 -22
  143. data/post-automake.rb +0 -28
  144. data/rice/Address_Registration_Guard.cpp +0 -22
  145. data/rice/Arg_impl.hpp +0 -129
  146. data/rice/Arg_operators.cpp +0 -21
  147. data/rice/Arg_operators.hpp +0 -19
  148. data/rice/Array.hpp +0 -214
  149. data/rice/Array.ipp +0 -256
  150. data/rice/Builtin_Object.hpp +0 -8
  151. data/rice/Builtin_Object.ipp +0 -50
  152. data/rice/Builtin_Object_defn.hpp +0 -50
  153. data/rice/Class.cpp +0 -57
  154. data/rice/Class.hpp +0 -8
  155. data/rice/Class.ipp +0 -6
  156. data/rice/Class_defn.hpp +0 -84
  157. data/rice/Data_Type.cpp +0 -54
  158. data/rice/Data_Type_fwd.hpp +0 -12
  159. data/rice/Director.cpp +0 -13
  160. data/rice/Exception.cpp +0 -54
  161. data/rice/Exception_Base.hpp +0 -8
  162. data/rice/Exception_Base.ipp +0 -13
  163. data/rice/Exception_Base_defn.hpp +0 -27
  164. data/rice/Hash.hpp +0 -230
  165. data/rice/Hash.ipp +0 -329
  166. data/rice/Identifier.cpp +0 -8
  167. data/rice/Jump_Tag.hpp +0 -24
  168. data/rice/Makefile.am +0 -121
  169. data/rice/Makefile.in +0 -884
  170. data/rice/Module.cpp +0 -84
  171. data/rice/Module.hpp +0 -8
  172. data/rice/Module.ipp +0 -6
  173. data/rice/Module_defn.hpp +0 -88
  174. data/rice/Module_impl.hpp +0 -281
  175. data/rice/Module_impl.ipp +0 -345
  176. data/rice/Object.cpp +0 -169
  177. data/rice/Object.hpp +0 -8
  178. data/rice/Object.ipp +0 -33
  179. data/rice/Object_defn.hpp +0 -214
  180. data/rice/Require_Guard.hpp +0 -21
  181. data/rice/String.cpp +0 -89
  182. data/rice/String.hpp +0 -91
  183. data/rice/Struct.cpp +0 -117
  184. data/rice/Struct.hpp +0 -162
  185. data/rice/Struct.ipp +0 -26
  186. data/rice/Symbol.cpp +0 -25
  187. data/rice/Symbol.hpp +0 -66
  188. data/rice/Symbol.ipp +0 -44
  189. data/rice/config.hpp +0 -47
  190. data/rice/config.hpp.in +0 -46
  191. data/rice/detail/Arguments.hpp +0 -118
  192. data/rice/detail/Auto_Function_Wrapper.hpp +0 -898
  193. data/rice/detail/Auto_Function_Wrapper.ipp +0 -3181
  194. data/rice/detail/Auto_Member_Function_Wrapper.hpp +0 -897
  195. data/rice/detail/Auto_Member_Function_Wrapper.ipp +0 -2501
  196. data/rice/detail/Caster.hpp +0 -103
  197. data/rice/detail/Not_Copyable.hpp +0 -25
  198. data/rice/detail/Wrapped_Function.hpp +0 -33
  199. data/rice/detail/cfp.hpp +0 -24
  200. data/rice/detail/cfp.ipp +0 -51
  201. data/rice/detail/check_ruby_type.cpp +0 -27
  202. data/rice/detail/check_ruby_type.hpp +0 -23
  203. data/rice/detail/creation_funcs.hpp +0 -37
  204. data/rice/detail/creation_funcs.ipp +0 -36
  205. data/rice/detail/define_method_and_auto_wrap.hpp +0 -31
  206. data/rice/detail/define_method_and_auto_wrap.ipp +0 -30
  207. data/rice/detail/demangle.cpp +0 -56
  208. data/rice/detail/demangle.hpp +0 -19
  209. data/rice/detail/env.hpp +0 -11
  210. data/rice/detail/method_data.cpp +0 -92
  211. data/rice/detail/node.hpp +0 -13
  212. data/rice/detail/protect.cpp +0 -29
  213. data/rice/detail/protect.hpp +0 -34
  214. data/rice/detail/ruby_version_code.hpp +0 -6
  215. data/rice/detail/ruby_version_code.hpp.in +0 -6
  216. data/rice/detail/st.hpp +0 -22
  217. data/rice/detail/win32.hpp +0 -16
  218. data/rice/detail/wrap_function.hpp +0 -66
  219. data/rice/protect.hpp +0 -38
  220. data/rice/protect.ipp +0 -1134
  221. data/rice/rubypp.rb +0 -97
  222. data/rice/to_from_ruby.hpp +0 -8
  223. data/rice/to_from_ruby.ipp +0 -418
  224. data/rice/to_from_ruby_defn.hpp +0 -70
  225. data/ruby/Makefile.am +0 -1
  226. data/ruby/Makefile.in +0 -628
  227. data/ruby/lib/Makefile.am +0 -3
  228. data/ruby/lib/Makefile.in +0 -506
  229. data/ruby/lib/mkmf-rice.rb.in +0 -217
  230. data/ruby/lib/version.rb +0 -3
  231. data/ruby.ac +0 -135
  232. data/sample/Makefile.am +0 -53
  233. data/sample/Makefile.in +0 -495
  234. data/test/Makefile.am +0 -73
  235. data/test/Makefile.in +0 -1219
  236. data/test/ext/Makefile.am +0 -41
  237. data/test/ext/Makefile.in +0 -483
  238. data/test/test_rice.rb +0 -45
@@ -0,0 +1,1113 @@
1
+ #ifndef Rice__stl__hpp_
2
+ #define Rice__stl__hpp_
3
+
4
+
5
+ // ========= string.hpp =========
6
+
7
+
8
+ // --------- string.ipp ---------
9
+ #include <string>
10
+
11
+ namespace Rice::detail
12
+ {
13
+ template<>
14
+ struct Type<std::string>
15
+ {
16
+ static bool verify()
17
+ {
18
+ return true;
19
+ }
20
+ };
21
+
22
+ template<>
23
+ class To_Ruby<std::string>
24
+ {
25
+ public:
26
+ VALUE convert(std::string const& x)
27
+ {
28
+ return detail::protect(rb_external_str_new, x.data(), (long)x.size());
29
+ }
30
+ };
31
+
32
+ template<>
33
+ class To_Ruby<std::string&>
34
+ {
35
+ public:
36
+ VALUE convert(std::string const& x)
37
+ {
38
+ return detail::protect(rb_external_str_new, x.data(), (long)x.size());
39
+ }
40
+ };
41
+
42
+ template<>
43
+ class From_Ruby<std::string>
44
+ {
45
+ public:
46
+ From_Ruby() = default;
47
+
48
+ explicit From_Ruby(Arg* arg) : arg_(arg)
49
+ {
50
+ }
51
+
52
+ std::string convert(VALUE value)
53
+ {
54
+ if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
55
+ {
56
+ return this->arg_->defaultValue<std::string>();
57
+ }
58
+ else
59
+ {
60
+ detail::protect(rb_check_type, value, (int)T_STRING);
61
+ return std::string(RSTRING_PTR(value), RSTRING_LEN(value));
62
+ }
63
+ }
64
+
65
+ private:
66
+ Arg* arg_ = nullptr;
67
+ };
68
+
69
+ template<>
70
+ class From_Ruby<std::string*>
71
+ {
72
+ public:
73
+ std::string* convert(VALUE value)
74
+ {
75
+ detail::protect(rb_check_type, value, (int)T_STRING);
76
+ this->converted_ = std::string(RSTRING_PTR(value), RSTRING_LEN(value));
77
+ return &this->converted_;
78
+ }
79
+
80
+ private:
81
+ std::string converted_;
82
+ };
83
+
84
+ template<>
85
+ class From_Ruby<std::string&>
86
+ {
87
+ public:
88
+ From_Ruby() = default;
89
+
90
+ explicit From_Ruby(Arg* arg) : arg_(arg)
91
+ {
92
+ }
93
+
94
+ std::string& convert(VALUE value)
95
+ {
96
+ if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
97
+ {
98
+ return this->arg_->defaultValue<std::string>();
99
+ }
100
+ else
101
+ {
102
+ detail::protect(rb_check_type, value, (int)T_STRING);
103
+ this->converted_ = std::string(RSTRING_PTR(value), RSTRING_LEN(value));
104
+ return this->converted_;
105
+ }
106
+ }
107
+
108
+ private:
109
+ Arg* arg_ = nullptr;
110
+ std::string converted_;
111
+ };
112
+ }
113
+
114
+ // ========= complex.hpp =========
115
+
116
+
117
+ // --------- complex.ipp ---------
118
+ #include <complex>
119
+
120
+
121
+ namespace Rice::detail
122
+ {
123
+ template<typename T>
124
+ struct Type<std::complex<T>>
125
+ {
126
+ static bool verify()
127
+ {
128
+ return true;
129
+ }
130
+ };
131
+
132
+ template<typename T>
133
+ class To_Ruby<std::complex<T>>
134
+ {
135
+ public:
136
+ VALUE convert(const std::complex<T>& data)
137
+ {
138
+ std::vector<VALUE> args(2);
139
+ args[0] = To_Ruby<T>().convert(data.real());
140
+ args[1] = To_Ruby<T>().convert(data.imag());
141
+ return protect(rb_funcall2, rb_mKernel, rb_intern("Complex"), (int)args.size(), (const VALUE*)args.data());
142
+ }
143
+ };
144
+
145
+ template<typename T>
146
+ class From_Ruby<std::complex<T>>
147
+ {
148
+ public:
149
+ std::complex<T> convert(VALUE value)
150
+ {
151
+ VALUE real = protect(rb_funcall2, value, rb_intern("real"), 0, (const VALUE*)nullptr);
152
+ VALUE imaginary = protect(rb_funcall2, value, rb_intern("imaginary"), 0, (const VALUE*)nullptr);
153
+
154
+ return std::complex<T>(From_Ruby<T>().convert(real), From_Ruby<T>().convert(imaginary));
155
+ }
156
+ };
157
+
158
+ template<typename T>
159
+ class From_Ruby<std::complex<T>&>
160
+ {
161
+ public:
162
+ std::complex<T>& convert(VALUE value)
163
+ {
164
+ VALUE real = protect(rb_funcall2, value, rb_intern("real"), 0, (const VALUE*)nullptr);
165
+ VALUE imaginary = protect(rb_funcall2, value, rb_intern("imaginary"), 0, (const VALUE*)nullptr);
166
+ this->converted_ = std::complex<T>(From_Ruby<T>().convert(real), From_Ruby<T>().convert(imaginary));
167
+
168
+ return this->converted_;
169
+ }
170
+
171
+ private:
172
+ std::complex<T> converted_;
173
+ };
174
+ }
175
+
176
+ // ========= optional.hpp =========
177
+
178
+
179
+ // --------- optional.ipp ---------
180
+ #include <optional>
181
+
182
+ namespace Rice::detail
183
+ {
184
+ template<typename T>
185
+ struct Type<std::optional<T>>
186
+ {
187
+ constexpr static bool verify()
188
+ {
189
+ return Type<T>::verify();
190
+ }
191
+ };
192
+
193
+ template<>
194
+ class To_Ruby<std::nullopt_t>
195
+ {
196
+ public:
197
+ VALUE convert(std::nullopt_t& _)
198
+ {
199
+ return Qnil;
200
+ }
201
+ };
202
+
203
+ template<typename T>
204
+ class To_Ruby<std::optional<T>>
205
+ {
206
+ public:
207
+ static VALUE convert(std::optional<T>& data, bool takeOwnership = false)
208
+ {
209
+ if (data.has_value())
210
+ {
211
+ return To_Ruby<T>().convert(data.value());
212
+ }
213
+ else
214
+ {
215
+ return Qnil;
216
+ }
217
+ }
218
+ };
219
+
220
+ template<typename T>
221
+ class To_Ruby<std::optional<T>&>
222
+ {
223
+ public:
224
+ static VALUE convert(std::optional<T>& data, bool takeOwnership = false)
225
+ {
226
+ if (data.has_value())
227
+ {
228
+ return To_Ruby<T>().convert(data.value());
229
+ }
230
+ else
231
+ {
232
+ return Qnil;
233
+ }
234
+ }
235
+ };
236
+
237
+ template<typename T>
238
+ class From_Ruby<std::optional<T>>
239
+ {
240
+ public:
241
+ std::optional<T> convert(VALUE value)
242
+ {
243
+ if (value == Qnil)
244
+ {
245
+ return std::nullopt;
246
+ }
247
+ else
248
+ {
249
+ return From_Ruby<T>().convert(value);
250
+ }
251
+ }
252
+ };
253
+
254
+ template<typename T>
255
+ class From_Ruby<std::optional<T>&>
256
+ {
257
+ public:
258
+ std::optional<T>& convert(VALUE value)
259
+ {
260
+ if (value == Qnil)
261
+ {
262
+ this->converted_ = std::nullopt;
263
+ }
264
+ else
265
+ {
266
+ this->converted_ = From_Ruby<T>().convert(value);
267
+ }
268
+ return this->converted_;
269
+ }
270
+
271
+ private:
272
+ std::optional<T> converted_;
273
+ };
274
+ }
275
+
276
+ // ========= pair.hpp =========
277
+
278
+
279
+ namespace Rice
280
+ {
281
+ template<typename T>
282
+ Data_Type<T> define_pair(std::string name);
283
+
284
+ template<typename T>
285
+ Data_Type<T> define_pair_under(Object module, std::string name);
286
+ }
287
+
288
+
289
+ // --------- pair.ipp ---------
290
+
291
+ #include <sstream>
292
+ #include <stdexcept>
293
+ #include <utility>
294
+
295
+ namespace Rice
296
+ {
297
+ namespace stl
298
+ {
299
+ template<typename T>
300
+ class PairHelper
301
+ {
302
+ public:
303
+ PairHelper(Data_Type<T> klass) : klass_(klass)
304
+ {
305
+ this->define_constructor();
306
+ this->define_copyable_methods();
307
+ this->define_access_methods();
308
+ this->define_modify_methods();
309
+ this->define_to_s();
310
+ }
311
+
312
+ private:
313
+ void define_constructor()
314
+ {
315
+ klass_.define_constructor(Constructor<T, typename T::first_type&, typename T::second_type&>());
316
+ }
317
+
318
+ void define_copyable_methods()
319
+ {
320
+ if constexpr (std::is_copy_constructible_v<typename T::first_type> && std::is_copy_constructible_v<typename T::second_type>)
321
+ {
322
+ klass_.define_method("copy", [](T& self) -> T
323
+ {
324
+ return self;
325
+ });
326
+ }
327
+ else
328
+ {
329
+ klass_.define_method("copy", [](T& self) -> T
330
+ {
331
+ throw std::runtime_error("Cannot copy pair with non-copy constructible types");
332
+ return self;
333
+ });
334
+ }
335
+ }
336
+
337
+ void define_access_methods()
338
+ {
339
+ // Access methods
340
+ klass_.define_method("first", [](T& self) -> typename T::first_type&
341
+ {
342
+ return self.first;
343
+ })
344
+ .define_method("second", [](T& self) -> typename T::second_type&
345
+ {
346
+ return self.second;
347
+ });
348
+ }
349
+
350
+ void define_modify_methods()
351
+ {
352
+ // Access methods
353
+ klass_.define_method("first=", [](T& self, typename T::first_type& value) -> typename T::first_type&
354
+ {
355
+ self.first = value;
356
+ return self.first;
357
+ })
358
+ .define_method("second=", [](T& self, typename T::second_type& value) -> typename T::second_type&
359
+ {
360
+ self.second = value;
361
+ return self.second;
362
+ });
363
+ }
364
+
365
+ void define_to_s()
366
+ {
367
+ if constexpr (detail::is_ostreamable_v<typename T::first_type> && detail::is_ostreamable_v<typename T::second_type>)
368
+ {
369
+ klass_.define_method("to_s", [](const T& self)
370
+ {
371
+ std::stringstream stream;
372
+ stream << "[" << self.first << ", " << self.second << "]";
373
+ return stream.str();
374
+ });
375
+ }
376
+ else
377
+ {
378
+ klass_.define_method("to_s", [](const T& self)
379
+ {
380
+ return "[Not printable]";
381
+ });
382
+ }
383
+ }
384
+
385
+ private:
386
+ Data_Type<T> klass_;
387
+ };
388
+ } // namespace
389
+
390
+ template<typename T>
391
+ Data_Type<T> define_pair_under(Object module, std::string name)
392
+ {
393
+ if (detail::TypeRegistry::isDefined<T>())
394
+ {
395
+ return Data_Type<T>(Data_Type<T>());
396
+ }
397
+
398
+ Data_Type<T> result = define_class_under<detail::intrinsic_type<T>>(module, name.c_str());
399
+ stl::PairHelper helper(result);
400
+ return result;
401
+ }
402
+
403
+ template<typename T>
404
+ Data_Type<T> define_pair(std::string name)
405
+ {
406
+ if (detail::TypeRegistry::isDefined<T>())
407
+ {
408
+ return Data_Type<T>(Data_Type<T>());
409
+ }
410
+
411
+ Data_Type<T> result = define_class<detail::intrinsic_type<T>>(name.c_str());
412
+ stl::PairHelper<T> helper(result);
413
+ return result;
414
+ }
415
+
416
+ template<typename T>
417
+ Data_Type<T> define_pair_auto()
418
+ {
419
+ std::string klassName = detail::makeClassName(typeid(T));
420
+ Module rb_mRice = define_module("Rice");
421
+ Module rb_mpair = define_module_under(rb_mRice, "Std");
422
+ return define_pair_under<T>(rb_mpair, klassName);
423
+ }
424
+
425
+ namespace detail
426
+ {
427
+ template<typename T1, typename T2>
428
+ struct Type<std::pair<T1, T2>>
429
+ {
430
+ static bool verify()
431
+ {
432
+ Type<T1>::verify();
433
+ Type<T2>::verify();
434
+
435
+ if (!detail::TypeRegistry::isDefined<std::pair<T1, T2>>())
436
+ {
437
+ define_pair_auto<std::pair<T1, T2>>();
438
+ }
439
+
440
+ return true;
441
+ }
442
+ };
443
+ }
444
+ }
445
+
446
+
447
+
448
+ // ========= smart_ptr.hpp =========
449
+
450
+
451
+ namespace Rice::detail
452
+ {
453
+ template <template <typename, typename...> typename SmartPointer_T, typename...Arg_Ts>
454
+ class WrapperSmartPointer : public Wrapper
455
+ {
456
+ public:
457
+ WrapperSmartPointer(SmartPointer_T<Arg_Ts...>& data);
458
+ void* get() override;
459
+ SmartPointer_T<Arg_Ts...>& data();
460
+
461
+ private:
462
+ SmartPointer_T<Arg_Ts...> data_;
463
+ };
464
+ }
465
+
466
+
467
+ // --------- smart_ptr.ipp ---------
468
+
469
+ #include <assert.h>
470
+ #include <memory>
471
+
472
+ namespace Rice::detail
473
+ {
474
+ // ---- WrapperSmartPointer ------
475
+ template <template <typename, typename...> typename SmartPointer_T, typename...Arg_Ts>
476
+ inline WrapperSmartPointer<SmartPointer_T, Arg_Ts...>::WrapperSmartPointer(SmartPointer_T<Arg_Ts...>& data)
477
+ : data_(std::move(data))
478
+ {
479
+ }
480
+
481
+ template <template <typename, typename...> typename SmartPointer_T, typename...Arg_Ts>
482
+ inline void* WrapperSmartPointer<SmartPointer_T, Arg_Ts...>::get()
483
+ {
484
+ return (void*)this->data_.get();
485
+ }
486
+
487
+ template <template <typename, typename...> typename SmartPointer_T, typename...Arg_Ts>
488
+ inline SmartPointer_T<Arg_Ts...>& WrapperSmartPointer<SmartPointer_T, Arg_Ts...>::data()
489
+ {
490
+ return data_;
491
+ }
492
+
493
+ // ---- unique_ptr ------
494
+ template <typename T>
495
+ class To_Ruby<std::unique_ptr<T>>
496
+ {
497
+ public:
498
+ VALUE convert(std::unique_ptr<T>& data)
499
+ {
500
+ std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::TypeRegistry::figureType<T>(*data);
501
+
502
+ // Use custom wrapper type
503
+ using Wrapper_T = WrapperSmartPointer<std::unique_ptr, T>;
504
+ return detail::wrap<std::unique_ptr<T>, Wrapper_T>(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
505
+ }
506
+ };
507
+
508
+ template <typename T>
509
+ class From_Ruby<std::unique_ptr<T>&>
510
+ {
511
+ public:
512
+ std::unique_ptr<T>& convert(VALUE value)
513
+ {
514
+ Wrapper* wrapper = detail::getWrapper(value, Data_Type<T>::rb_type());
515
+
516
+ using Wrapper_T = WrapperSmartPointer<std::unique_ptr, T>;
517
+ Wrapper_T* smartWrapper = dynamic_cast<Wrapper_T*>(wrapper);
518
+ if (!smartWrapper)
519
+ {
520
+ std::string message = "Invalid smart pointer wrapper";
521
+ throw std::runtime_error(message.c_str());
522
+ }
523
+ return smartWrapper->data();
524
+ }
525
+ };
526
+
527
+ template<typename T>
528
+ struct Type<std::unique_ptr<T>>
529
+ {
530
+ static bool verify()
531
+ {
532
+ return Type<T>::verify();
533
+ }
534
+ };
535
+
536
+ // ----- shared_ptr -------------
537
+ template <typename T>
538
+ class To_Ruby<std::shared_ptr<T>>
539
+ {
540
+ public:
541
+ VALUE convert(std::shared_ptr<T>& data)
542
+ {
543
+ std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::TypeRegistry::figureType<T>(*data);
544
+
545
+ // Use custom wrapper type
546
+ using Wrapper_T = WrapperSmartPointer<std::shared_ptr, T>;
547
+ return detail::wrap<std::shared_ptr<T>, Wrapper_T>(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
548
+ }
549
+ };
550
+
551
+ template <typename T>
552
+ class From_Ruby<std::shared_ptr<T>>
553
+ {
554
+ public:
555
+ std::shared_ptr<T> convert(VALUE value)
556
+ {
557
+ Wrapper* wrapper = detail::getWrapper(value, Data_Type<T>::rb_type());
558
+
559
+ using Wrapper_T = WrapperSmartPointer<std::shared_ptr, T>;
560
+ Wrapper_T* smartWrapper = dynamic_cast<Wrapper_T*>(wrapper);
561
+ if (!smartWrapper)
562
+ {
563
+ std::string message = "Invalid smart pointer wrapper";
564
+ throw std::runtime_error(message.c_str());
565
+ }
566
+ return smartWrapper->data();
567
+ }
568
+ };
569
+
570
+ template <typename T>
571
+ class From_Ruby<std::shared_ptr<T>&>
572
+ {
573
+ public:
574
+ std::shared_ptr<T>& convert(VALUE value)
575
+ {
576
+ Wrapper* wrapper = detail::getWrapper(value, Data_Type<T>::rb_type());
577
+
578
+ using Wrapper_T = WrapperSmartPointer<std::shared_ptr, T>;
579
+ Wrapper_T* smartWrapper = dynamic_cast<Wrapper_T*>(wrapper);
580
+ if (!smartWrapper)
581
+ {
582
+ std::string message = "Invalid smart pointer wrapper";
583
+ throw std::runtime_error(message.c_str());
584
+ }
585
+ return smartWrapper->data();
586
+ }
587
+ };
588
+
589
+ template<typename T>
590
+ struct Type<std::shared_ptr<T>>
591
+ {
592
+ static bool verify()
593
+ {
594
+ return Type<T>::verify();
595
+ }
596
+ };
597
+ }
598
+
599
+ // ========= vector.hpp =========
600
+
601
+
602
+ namespace Rice
603
+ {
604
+ template<typename T>
605
+ Data_Type<T> define_vector(std::string name);
606
+
607
+ template<typename T>
608
+ Data_Type<T> define_vector_under(Object module, std::string name);
609
+ }
610
+
611
+
612
+ // --------- vector.ipp ---------
613
+
614
+ #include <sstream>
615
+ #include <stdexcept>
616
+ #include <vector>
617
+
618
+ namespace Rice
619
+ {
620
+ namespace stl
621
+ {
622
+ template<typename T>
623
+ class VectorHelper
624
+ {
625
+ using Value_T = typename T::value_type;
626
+ using Size_T = typename T::size_type;
627
+ using Difference_T = typename T::difference_type;
628
+
629
+ public:
630
+ VectorHelper(Data_Type<T> klass) : klass_(klass)
631
+ {
632
+ this->define_constructor();
633
+ this->define_copyable_methods();
634
+ this->define_constructable_methods();
635
+ this->define_capacity_methods();
636
+ this->define_access_methods();
637
+ this->define_comparable_methods();
638
+ this->define_modify_methods();
639
+ this->define_to_s();
640
+ this->define_enumerable();
641
+ }
642
+
643
+ private:
644
+
645
+ // Helper method to translate Ruby indices to vector indices
646
+ Difference_T normalizeIndex(Size_T size, Difference_T index, bool enforceBounds = false)
647
+ {
648
+ // Negative indices mean count from the right. Note that negative indices
649
+ // wrap around!
650
+ if (index < 0)
651
+ {
652
+ index = ((-index) % size);
653
+ index = index > 0 ? size - index : index;
654
+ }
655
+
656
+ if (enforceBounds && (index < 0 || index >= (Difference_T)size))
657
+ {
658
+ throw std::out_of_range("Invalid index: " + std::to_string(index));
659
+ }
660
+
661
+ return index;
662
+ };
663
+
664
+ void define_constructor()
665
+ {
666
+ klass_.define_constructor(Constructor<T>());
667
+ }
668
+
669
+ void define_copyable_methods()
670
+ {
671
+ if constexpr (std::is_copy_constructible_v<Value_T>)
672
+ {
673
+ klass_.define_method("copy", [](T& self) -> T
674
+ {
675
+ return self;
676
+ });
677
+ }
678
+ else
679
+ {
680
+ klass_.define_method("copy", [](T& self) -> T
681
+ {
682
+ throw std::runtime_error("Cannot copy vectors with non-copy constructible types");
683
+ return self;
684
+ });
685
+ }
686
+ }
687
+
688
+ void define_constructable_methods()
689
+ {
690
+ if constexpr (std::is_default_constructible_v<Value_T>)
691
+ {
692
+ klass_.define_method("resize", static_cast<void (T::*)(const size_t)>(&T::resize));
693
+ }
694
+ else
695
+ {
696
+ klass_.define_method("resize", [](const T& self, Size_T newSize)
697
+ {
698
+ // Do nothing
699
+ });
700
+ }
701
+ }
702
+
703
+ void define_capacity_methods()
704
+ {
705
+ klass_.define_method("empty?", &T::empty)
706
+ .define_method("capacity", &T::capacity)
707
+ .define_method("max_size", &T::max_size)
708
+ .define_method("reserve", &T::reserve)
709
+ .define_method("size", &T::size);
710
+
711
+ rb_define_alias(klass_, "count", "size");
712
+ rb_define_alias(klass_, "length", "size");
713
+ //detail::protect(rb_define_alias, klass_, "count", "size");
714
+ //detail::protect(rb_define_alias, klass_, "length", "size");
715
+ }
716
+
717
+ void define_access_methods()
718
+ {
719
+ // Access methods
720
+ klass_.define_method("first", [](const T& self) -> std::optional<Value_T>
721
+ {
722
+ if (self.size() > 0)
723
+ {
724
+ return self.front();
725
+ }
726
+ else
727
+ {
728
+ return std::nullopt;
729
+ }
730
+ })
731
+ .define_method("last", [](const T& self) -> std::optional<Value_T>
732
+ {
733
+ if (self.size() > 0)
734
+ {
735
+ return self.back();
736
+ }
737
+ else
738
+ {
739
+ return std::nullopt;
740
+ }
741
+ })
742
+ .define_method("[]", [this](const T& self, Difference_T index) -> std::optional<Value_T>
743
+ {
744
+ index = normalizeIndex(self.size(), index);
745
+ if (index < 0 || index >= (Difference_T)self.size())
746
+ {
747
+ return std::nullopt;
748
+ }
749
+ else
750
+ {
751
+ return self[index];
752
+ }
753
+ });
754
+
755
+ rb_define_alias(klass_, "at", "[]");
756
+ }
757
+
758
+ // Methods that require Value_T to support operator==
759
+ void define_comparable_methods()
760
+ {
761
+ if constexpr (detail::is_comparable_v<Value_T>)
762
+ {
763
+ klass_.define_method("delete", [](T& self, Value_T& element) -> std::optional<Value_T>
764
+ {
765
+ auto iter = std::find(self.begin(), self.end(), element);
766
+ if (iter == self.end())
767
+ {
768
+ return std::nullopt;
769
+ }
770
+ else
771
+ {
772
+ Value_T result = *iter;
773
+ self.erase(iter);
774
+ return result;
775
+ }
776
+ })
777
+ .define_method("include?", [](T& self, Value_T& element)
778
+ {
779
+ return std::find(self.begin(), self.end(), element) != self.end();
780
+ })
781
+ .define_method("index", [](T& self, Value_T& element) -> std::optional<Difference_T>
782
+ {
783
+ auto iter = std::find(self.begin(), self.end(), element);
784
+ if (iter == self.end())
785
+ {
786
+ return std::nullopt;
787
+ }
788
+ else
789
+ {
790
+ return iter - self.begin();
791
+ }
792
+ });
793
+ }
794
+ else
795
+ {
796
+ klass_.define_method("delete", [](T& self, Value_T& element) -> std::optional<Value_T>
797
+ {
798
+ return std::nullopt;
799
+ })
800
+ .define_method("include?", [](const T& self, Value_T& element)
801
+ {
802
+ return false;
803
+ })
804
+ .define_method("index", [](const T& self, Value_T& element) -> std::optional<Difference_T>
805
+ {
806
+ return std::nullopt;
807
+ });
808
+ }
809
+ }
810
+
811
+ void define_modify_methods()
812
+ {
813
+ klass_.define_method("clear", &T::clear)
814
+ .define_method("delete_at", [](T& self, const size_t& pos)
815
+ {
816
+ auto iter = self.begin() + pos;
817
+ Value_T result = *iter;
818
+ self.erase(iter);
819
+ return result;
820
+ })
821
+ .define_method("insert", [this](T& self, Difference_T index, Value_T& element) -> T&
822
+ {
823
+ index = normalizeIndex(self.size(), index, true);
824
+ auto iter = self.begin() + index;
825
+ self.insert(iter, element);
826
+ return self;
827
+ })
828
+ .define_method("pop", [](T& self) -> std::optional<Value_T>
829
+ {
830
+ if (self.size() > 0)
831
+ {
832
+ Value_T result = self.back();
833
+ self.pop_back();
834
+ return result;
835
+ }
836
+ else
837
+ {
838
+ return std::nullopt;
839
+ }
840
+ })
841
+ .define_method("push", [](T& self, Value_T& element) -> T&
842
+ {
843
+ self.push_back(element);
844
+ return self;
845
+ })
846
+ .define_method("shrink_to_fit", &T::shrink_to_fit)
847
+ .define_method("[]=", [this](T& self, Difference_T index, Value_T& element) -> Value_T&
848
+ {
849
+ index = normalizeIndex(self.size(), index, true);
850
+ self[index] = element;
851
+ return element;
852
+ });
853
+
854
+ rb_define_alias(klass_, "<<", "push");
855
+ rb_define_alias(klass_, "append", "push");
856
+ }
857
+
858
+ void define_enumerable()
859
+ {
860
+ // Add enumerable support
861
+ klass_.include_module(rb_mEnumerable)
862
+ .define_method("each", [](T& self) -> const T&
863
+ {
864
+ for (Value_T& item : self)
865
+ {
866
+ VALUE element = detail::To_Ruby<Value_T>().convert(item);
867
+ rb_yield(element);
868
+ }
869
+ return self;
870
+ });
871
+ }
872
+
873
+ void define_to_s()
874
+ {
875
+ if constexpr (detail::is_ostreamable_v<Value_T>)
876
+ {
877
+ klass_.define_method("to_s", [](const T& self)
878
+ {
879
+ auto iter = self.begin();
880
+ auto finish = self.size() > 1000 ? self.begin() + 1000 : self.end();
881
+
882
+ std::stringstream stream;
883
+ stream << "[";
884
+
885
+ for (; iter != finish; iter++)
886
+ {
887
+ if (iter == self.begin())
888
+ {
889
+ stream << *iter;
890
+ }
891
+ else
892
+ {
893
+ stream << ", " << *iter;
894
+ }
895
+ }
896
+
897
+ stream << "]";
898
+ return stream.str();
899
+ });
900
+ }
901
+ else
902
+ {
903
+ klass_.define_method("to_s", [](const T& self)
904
+ {
905
+ return "[Not printable]";
906
+ });
907
+ }
908
+ }
909
+
910
+ private:
911
+ Data_Type<T> klass_;
912
+ };
913
+ } // namespace
914
+
915
+ template<typename T>
916
+ Data_Type<T> define_vector_under(Object module, std::string name)
917
+ {
918
+ if (detail::TypeRegistry::isDefined<T>())
919
+ {
920
+ return Data_Type<T>(Data_Type<T>());
921
+ }
922
+
923
+ Data_Type<T> result = define_class_under<detail::intrinsic_type<T>>(module, name.c_str());
924
+ stl::VectorHelper helper(result);
925
+ return result;
926
+ }
927
+
928
+ template<typename T>
929
+ Data_Type<T> define_vector(std::string name)
930
+ {
931
+ if (detail::TypeRegistry::isDefined<T>())
932
+ {
933
+ return Data_Type<T>(Data_Type<T>());
934
+ }
935
+
936
+ Data_Type<T> result = define_class<detail::intrinsic_type<T>>(name.c_str());
937
+ stl::VectorHelper<T> helper(result);
938
+ return result;
939
+ }
940
+
941
+ template<typename T>
942
+ Data_Type<T> define_vector_auto()
943
+ {
944
+ std::string klassName = detail::makeClassName(typeid(T));
945
+ Module rb_mRice = define_module("Rice");
946
+ Module rb_mVector = define_module_under(rb_mRice, "Std");
947
+ return define_vector_under<T>(rb_mVector, klassName);
948
+ }
949
+
950
+ namespace detail
951
+ {
952
+ template<typename T>
953
+ struct Type<std::vector<T>>
954
+ {
955
+ static bool verify()
956
+ {
957
+ Type<T>::verify();
958
+
959
+ if (!detail::TypeRegistry::isDefined<std::vector<T>>())
960
+ {
961
+ define_vector_auto<std::vector<T>>();
962
+ }
963
+
964
+ return true;
965
+ }
966
+ };
967
+
968
+ template<typename T>
969
+ std::vector<T> vectorFromArray(VALUE value)
970
+ {
971
+ size_t length = protect(rb_array_len, value);
972
+ std::vector<T> result(length);
973
+
974
+ for (long i = 0; i < length; i++)
975
+ {
976
+ VALUE element = protect(rb_ary_entry, value, i);
977
+ result[i] = From_Ruby<T>().convert(element);
978
+ }
979
+
980
+ return result;
981
+ }
982
+
983
+ template<typename T>
984
+ class From_Ruby<std::vector<T>>
985
+ {
986
+ public:
987
+ From_Ruby() = default;
988
+
989
+ explicit From_Ruby(Arg * arg) : arg_(arg)
990
+ {
991
+ }
992
+
993
+ std::vector<T> convert(VALUE value)
994
+ {
995
+ switch (rb_type(value))
996
+ {
997
+ case T_DATA:
998
+ {
999
+ // This is a wrapped vector (hopefully!)
1000
+ return *Data_Object<std::vector<T>>::from_ruby(value);
1001
+ }
1002
+ case T_ARRAY:
1003
+ {
1004
+ // If this an Ruby array and the vector type is copyable
1005
+ if constexpr (std::is_default_constructible_v<T>)
1006
+ {
1007
+ return vectorFromArray<T>(value);
1008
+ }
1009
+ }
1010
+ case T_NIL:
1011
+ {
1012
+ if (this->arg_ && this->arg_->hasDefaultValue())
1013
+ {
1014
+ return this->arg_->template defaultValue<std::vector<T>>();
1015
+ }
1016
+ }
1017
+ default:
1018
+ {
1019
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
1020
+ detail::protect(rb_obj_classname, value), "std::vector");
1021
+ }
1022
+ }
1023
+ }
1024
+
1025
+ private:
1026
+ Arg* arg_ = nullptr;
1027
+ };
1028
+
1029
+ template<typename T>
1030
+ class From_Ruby<std::vector<T>&>
1031
+ {
1032
+ public:
1033
+ From_Ruby() = default;
1034
+
1035
+ explicit From_Ruby(Arg * arg) : arg_(arg)
1036
+ {
1037
+ }
1038
+
1039
+ std::vector<T>& convert(VALUE value)
1040
+ {
1041
+ switch (rb_type(value))
1042
+ {
1043
+ case T_DATA:
1044
+ {
1045
+ // This is a wrapped vector (hopefully!)
1046
+ return *Data_Object<std::vector<T>>::from_ruby(value);
1047
+ }
1048
+ case T_ARRAY:
1049
+ {
1050
+ // If this an Ruby array and the vector type is copyable
1051
+ if constexpr (std::is_default_constructible_v<T>)
1052
+ {
1053
+ this->converted_ = vectorFromArray<T>(value);
1054
+ return this->converted_;
1055
+ }
1056
+ }
1057
+ case T_NIL:
1058
+ {
1059
+ if (this->arg_ && this->arg_->hasDefaultValue())
1060
+ {
1061
+ return this->arg_->template defaultValue<std::vector<T>>();
1062
+ }
1063
+ }
1064
+ default:
1065
+ {
1066
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
1067
+ detail::protect(rb_obj_classname, value), "std::vector");
1068
+ }
1069
+ }
1070
+ }
1071
+
1072
+ private:
1073
+ Arg* arg_ = nullptr;
1074
+ std::vector<T> converted_;
1075
+ };
1076
+
1077
+ template<typename T>
1078
+ class From_Ruby<std::vector<T>*>
1079
+ {
1080
+ public:
1081
+ std::vector<T>* convert(VALUE value)
1082
+ {
1083
+ switch (rb_type(value))
1084
+ {
1085
+ case T_DATA:
1086
+ {
1087
+ // This is a wrapped vector (hopefully!)
1088
+ return Data_Object<std::vector<T>>::from_ruby(value);
1089
+ }
1090
+ case T_ARRAY:
1091
+ {
1092
+ // If this an Ruby array and the vector type is copyable
1093
+ if constexpr (std::is_default_constructible_v<T>)
1094
+ {
1095
+ this->converted_ = vectorFromArray<T>(value);
1096
+ return &this->converted_;
1097
+ }
1098
+ }
1099
+ default:
1100
+ {
1101
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
1102
+ detail::protect(rb_obj_classname, value), "std::vector");
1103
+ }
1104
+ }
1105
+ }
1106
+
1107
+ private:
1108
+ std::vector<T> converted_;
1109
+ };
1110
+ }
1111
+ }
1112
+
1113
+ #endif // Rice__stl__hpp_