rice 2.1.3 → 4.0.2

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 (246) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +121 -0
  3. data/CONTRIBUTORS.md +19 -0
  4. data/COPYING +2 -2
  5. data/Gemfile +3 -0
  6. data/README.md +45 -1028
  7. data/Rakefile +95 -12
  8. data/include/rice/rice.hpp +7766 -0
  9. data/include/rice/stl.hpp +1113 -0
  10. data/lib/mkmf-rice.rb +127 -0
  11. data/lib/version.rb +3 -0
  12. data/rice/Address_Registration_Guard.ipp +75 -32
  13. data/rice/Address_Registration_Guard_defn.hpp +60 -56
  14. data/rice/Arg.hpp +80 -4
  15. data/rice/Arg.ipp +51 -0
  16. data/rice/Constructor.hpp +30 -376
  17. data/rice/Data_Object.ipp +234 -107
  18. data/rice/Data_Object_defn.hpp +77 -117
  19. data/rice/Data_Type.hpp +1 -2
  20. data/rice/Data_Type.ipp +251 -295
  21. data/rice/Data_Type_defn.hpp +175 -243
  22. data/rice/Director.hpp +14 -9
  23. data/rice/Enum.hpp +54 -104
  24. data/rice/Enum.ipp +104 -230
  25. data/rice/Exception.hpp +2 -8
  26. data/rice/Exception.ipp +65 -0
  27. data/rice/Exception_defn.hpp +46 -47
  28. data/rice/Identifier.hpp +28 -28
  29. data/rice/Identifier.ipp +23 -27
  30. data/rice/Return.hpp +39 -0
  31. data/rice/Return.ipp +33 -0
  32. data/rice/detail/Exception_Handler.ipp +22 -62
  33. data/rice/detail/Exception_Handler_defn.hpp +76 -91
  34. data/rice/detail/Iterator.hpp +18 -88
  35. data/rice/detail/Iterator.ipp +47 -0
  36. data/rice/detail/Jump_Tag.hpp +21 -0
  37. data/rice/detail/MethodInfo.hpp +44 -0
  38. data/rice/detail/MethodInfo.ipp +78 -0
  39. data/rice/detail/NativeAttribute.hpp +53 -0
  40. data/rice/detail/NativeAttribute.ipp +83 -0
  41. data/rice/detail/NativeFunction.hpp +69 -0
  42. data/rice/detail/NativeFunction.ipp +248 -0
  43. data/rice/detail/RubyFunction.hpp +39 -0
  44. data/rice/detail/RubyFunction.ipp +92 -0
  45. data/rice/detail/Type.hpp +29 -0
  46. data/rice/detail/Type.ipp +138 -0
  47. data/rice/detail/TypeRegistry.hpp +50 -0
  48. data/rice/detail/TypeRegistry.ipp +106 -0
  49. data/rice/detail/Wrapper.hpp +51 -0
  50. data/rice/detail/Wrapper.ipp +151 -0
  51. data/rice/detail/default_allocation_func.hpp +8 -19
  52. data/rice/detail/default_allocation_func.ipp +9 -8
  53. data/rice/detail/from_ruby.hpp +2 -37
  54. data/rice/detail/from_ruby.ipp +1020 -46
  55. data/rice/detail/from_ruby_defn.hpp +38 -0
  56. data/rice/detail/function_traits.hpp +124 -0
  57. data/rice/detail/method_data.hpp +23 -15
  58. data/rice/detail/method_data.ipp +53 -0
  59. data/rice/detail/rice_traits.hpp +116 -0
  60. data/rice/detail/ruby.hpp +9 -50
  61. data/rice/detail/to_ruby.hpp +3 -17
  62. data/rice/detail/to_ruby.ipp +409 -31
  63. data/rice/detail/to_ruby_defn.hpp +48 -0
  64. data/rice/forward_declares.ipp +82 -0
  65. data/rice/global_function.hpp +16 -20
  66. data/rice/global_function.ipp +8 -17
  67. data/rice/rice.hpp +59 -0
  68. data/rice/ruby_mark.hpp +5 -3
  69. data/rice/ruby_try_catch.hpp +4 -4
  70. data/rice/stl.hpp +11 -0
  71. data/sample/callbacks/extconf.rb +6 -0
  72. data/sample/callbacks/sample_callbacks.cpp +35 -0
  73. data/sample/callbacks/test.rb +28 -0
  74. data/sample/enum/extconf.rb +3 -0
  75. data/sample/enum/sample_enum.cpp +3 -17
  76. data/sample/enum/test.rb +2 -2
  77. data/sample/inheritance/animals.cpp +8 -24
  78. data/sample/inheritance/extconf.rb +3 -0
  79. data/sample/inheritance/test.rb +1 -1
  80. data/sample/map/extconf.rb +3 -0
  81. data/sample/map/map.cpp +10 -18
  82. data/sample/map/test.rb +1 -1
  83. data/test/embed_ruby.cpp +34 -0
  84. data/test/embed_ruby.hpp +4 -0
  85. data/test/ext/t1/extconf.rb +3 -0
  86. data/test/ext/t1/t1.cpp +1 -3
  87. data/test/ext/t2/extconf.rb +3 -0
  88. data/test/ext/t2/t2.cpp +1 -1
  89. data/test/extconf.rb +23 -0
  90. data/test/ruby/test_callbacks_sample.rb +28 -0
  91. data/test/ruby/test_multiple_extensions.rb +18 -0
  92. data/test/ruby/test_multiple_extensions_same_class.rb +14 -0
  93. data/test/ruby/test_multiple_extensions_with_inheritance.rb +20 -0
  94. data/test/test_Address_Registration_Guard.cpp +25 -11
  95. data/test/test_Array.cpp +131 -74
  96. data/test/test_Attribute.cpp +147 -0
  97. data/test/test_Builtin_Object.cpp +36 -15
  98. data/test/test_Class.cpp +151 -276
  99. data/test/test_Constructor.cpp +10 -9
  100. data/test/test_Data_Object.cpp +135 -193
  101. data/test/test_Data_Type.cpp +323 -252
  102. data/test/test_Director.cpp +56 -42
  103. data/test/test_Enum.cpp +230 -104
  104. data/test/test_Exception.cpp +7 -7
  105. data/test/test_Hash.cpp +33 -31
  106. data/test/test_Identifier.cpp +6 -6
  107. data/test/test_Inheritance.cpp +221 -0
  108. data/test/test_Iterator.cpp +161 -0
  109. data/test/test_Jump_Tag.cpp +1 -1
  110. data/test/test_Keep_Alive.cpp +161 -0
  111. data/test/test_Memory_Management.cpp +4 -5
  112. data/test/test_Module.cpp +169 -111
  113. data/test/test_Object.cpp +51 -19
  114. data/test/test_Ownership.cpp +275 -0
  115. data/test/test_Self.cpp +205 -0
  116. data/test/test_Stl_Optional.cpp +90 -0
  117. data/test/test_Stl_Pair.cpp +144 -0
  118. data/test/test_Stl_SmartPointer.cpp +200 -0
  119. data/test/test_Stl_String.cpp +74 -0
  120. data/test/test_Stl_Vector.cpp +652 -0
  121. data/test/test_String.cpp +3 -3
  122. data/test/test_Struct.cpp +31 -40
  123. data/test/test_Symbol.cpp +3 -3
  124. data/test/test_To_From_Ruby.cpp +283 -218
  125. data/test/test_global_functions.cpp +41 -20
  126. data/test/unittest.cpp +34 -8
  127. data/test/unittest.hpp +0 -4
  128. metadata +121 -136
  129. data/Doxyfile +0 -2268
  130. data/Makefile.am +0 -26
  131. data/Makefile.in +0 -923
  132. data/README.mingw +0 -8
  133. data/aclocal.m4 +0 -1088
  134. data/bootstrap +0 -8
  135. data/check_stdcxx_11.ac +0 -103
  136. data/config.guess +0 -1421
  137. data/config.sub +0 -1807
  138. data/configure +0 -7367
  139. data/configure.ac +0 -55
  140. data/depcomp +0 -791
  141. data/doxygen.ac +0 -314
  142. data/doxygen.am +0 -186
  143. data/extconf.rb +0 -69
  144. data/install-sh +0 -501
  145. data/missing +0 -215
  146. data/post-autoconf.rb +0 -22
  147. data/post-automake.rb +0 -28
  148. data/rice/Address_Registration_Guard.cpp +0 -22
  149. data/rice/Arg_impl.hpp +0 -129
  150. data/rice/Arg_operators.cpp +0 -21
  151. data/rice/Arg_operators.hpp +0 -19
  152. data/rice/Array.hpp +0 -214
  153. data/rice/Array.ipp +0 -256
  154. data/rice/Builtin_Object.hpp +0 -8
  155. data/rice/Builtin_Object.ipp +0 -50
  156. data/rice/Builtin_Object_defn.hpp +0 -50
  157. data/rice/Class.cpp +0 -57
  158. data/rice/Class.hpp +0 -8
  159. data/rice/Class.ipp +0 -6
  160. data/rice/Class_defn.hpp +0 -83
  161. data/rice/Data_Type.cpp +0 -54
  162. data/rice/Data_Type_fwd.hpp +0 -12
  163. data/rice/Director.cpp +0 -13
  164. data/rice/Exception.cpp +0 -59
  165. data/rice/Exception_Base.hpp +0 -8
  166. data/rice/Exception_Base.ipp +0 -13
  167. data/rice/Exception_Base_defn.hpp +0 -27
  168. data/rice/Hash.hpp +0 -227
  169. data/rice/Hash.ipp +0 -329
  170. data/rice/Identifier.cpp +0 -8
  171. data/rice/Jump_Tag.hpp +0 -24
  172. data/rice/Makefile.am +0 -125
  173. data/rice/Makefile.in +0 -888
  174. data/rice/Module.cpp +0 -84
  175. data/rice/Module.hpp +0 -8
  176. data/rice/Module.ipp +0 -6
  177. data/rice/Module_defn.hpp +0 -88
  178. data/rice/Module_impl.hpp +0 -281
  179. data/rice/Module_impl.ipp +0 -345
  180. data/rice/Object.cpp +0 -169
  181. data/rice/Object.hpp +0 -8
  182. data/rice/Object.ipp +0 -19
  183. data/rice/Object_defn.hpp +0 -191
  184. data/rice/Require_Guard.hpp +0 -21
  185. data/rice/String.cpp +0 -94
  186. data/rice/String.hpp +0 -91
  187. data/rice/Struct.cpp +0 -117
  188. data/rice/Struct.hpp +0 -162
  189. data/rice/Struct.ipp +0 -26
  190. data/rice/Symbol.cpp +0 -25
  191. data/rice/Symbol.hpp +0 -66
  192. data/rice/Symbol.ipp +0 -44
  193. data/rice/config.hpp +0 -47
  194. data/rice/config.hpp.in +0 -46
  195. data/rice/detail/Arguments.hpp +0 -118
  196. data/rice/detail/Auto_Function_Wrapper.hpp +0 -898
  197. data/rice/detail/Auto_Function_Wrapper.ipp +0 -3694
  198. data/rice/detail/Auto_Member_Function_Wrapper.hpp +0 -897
  199. data/rice/detail/Auto_Member_Function_Wrapper.ipp +0 -2774
  200. data/rice/detail/Caster.hpp +0 -103
  201. data/rice/detail/Not_Copyable.hpp +0 -25
  202. data/rice/detail/Wrapped_Function.hpp +0 -33
  203. data/rice/detail/cfp.hpp +0 -24
  204. data/rice/detail/cfp.ipp +0 -51
  205. data/rice/detail/check_ruby_type.cpp +0 -27
  206. data/rice/detail/check_ruby_type.hpp +0 -23
  207. data/rice/detail/creation_funcs.hpp +0 -37
  208. data/rice/detail/creation_funcs.ipp +0 -36
  209. data/rice/detail/define_method_and_auto_wrap.hpp +0 -31
  210. data/rice/detail/define_method_and_auto_wrap.ipp +0 -30
  211. data/rice/detail/demangle.cpp +0 -56
  212. data/rice/detail/demangle.hpp +0 -19
  213. data/rice/detail/env.hpp +0 -11
  214. data/rice/detail/method_data.cpp +0 -86
  215. data/rice/detail/node.hpp +0 -13
  216. data/rice/detail/object_call.hpp +0 -69
  217. data/rice/detail/object_call.ipp +0 -131
  218. data/rice/detail/protect.cpp +0 -29
  219. data/rice/detail/protect.hpp +0 -34
  220. data/rice/detail/ruby_version_code.hpp +0 -6
  221. data/rice/detail/ruby_version_code.hpp.in +0 -6
  222. data/rice/detail/st.hpp +0 -22
  223. data/rice/detail/traits.hpp +0 -43
  224. data/rice/detail/win32.hpp +0 -16
  225. data/rice/detail/wrap_function.hpp +0 -341
  226. data/rice/detail/wrap_function.ipp +0 -514
  227. data/rice/protect.hpp +0 -92
  228. data/rice/protect.ipp +0 -1134
  229. data/rice/rubypp.rb +0 -97
  230. data/rice/to_from_ruby.hpp +0 -8
  231. data/rice/to_from_ruby.ipp +0 -294
  232. data/rice/to_from_ruby_defn.hpp +0 -70
  233. data/ruby.ac +0 -135
  234. data/ruby/Makefile.am +0 -1
  235. data/ruby/Makefile.in +0 -628
  236. data/ruby/lib/Makefile.am +0 -3
  237. data/ruby/lib/Makefile.in +0 -506
  238. data/ruby/lib/mkmf-rice.rb.in +0 -217
  239. data/ruby/lib/version.rb +0 -3
  240. data/sample/Makefile.am +0 -47
  241. data/sample/Makefile.in +0 -489
  242. data/test/Makefile.am +0 -72
  243. data/test/Makefile.in +0 -1213
  244. data/test/ext/Makefile.am +0 -41
  245. data/test/ext/Makefile.in +0 -483
  246. data/test/test_rice.rb +0 -41
@@ -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_