rice 3.0.0 → 4.0.3

Sign up to get free protection for your applications and to get access to all the features.
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_