rice 4.3.3 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +86 -26
  3. data/CMakeLists.txt +31 -0
  4. data/CMakePresets.json +75 -0
  5. data/COPYING +3 -2
  6. data/FindRuby.cmake +437 -0
  7. data/README.md +7 -2
  8. data/Rakefile +12 -5
  9. data/include/rice/rice.hpp +9522 -4426
  10. data/include/rice/stl.hpp +2831 -1198
  11. data/lib/make_rice_headers.rb +79 -0
  12. data/lib/mkmf-rice.rb +40 -94
  13. data/lib/rice/version.rb +3 -0
  14. data/lib/rice.rb +1 -0
  15. data/lib/rubygems/builder.rb +11 -0
  16. data/lib/rubygems/cmake_builder.rb +113 -0
  17. data/lib/rubygems_plugin.rb +9 -0
  18. data/rice/Address_Registration_Guard.hpp +72 -3
  19. data/rice/Arg.hpp +26 -6
  20. data/rice/Arg.ipp +35 -2
  21. data/rice/Buffer.hpp +123 -0
  22. data/rice/Buffer.ipp +599 -0
  23. data/rice/Callback.hpp +21 -0
  24. data/rice/Callback.ipp +13 -0
  25. data/rice/Constructor.hpp +4 -27
  26. data/rice/Constructor.ipp +79 -0
  27. data/rice/Data_Object.hpp +73 -3
  28. data/rice/Data_Object.ipp +388 -96
  29. data/rice/Data_Type.hpp +214 -3
  30. data/rice/Data_Type.ipp +144 -67
  31. data/rice/Director.hpp +0 -2
  32. data/rice/Enum.hpp +4 -7
  33. data/rice/Enum.ipp +102 -55
  34. data/rice/Exception.hpp +62 -2
  35. data/rice/Exception.ipp +7 -12
  36. data/rice/Init.hpp +8 -0
  37. data/rice/Init.ipp +8 -0
  38. data/rice/JumpException.hpp +44 -0
  39. data/rice/JumpException.ipp +48 -0
  40. data/rice/MemoryView.hpp +11 -0
  41. data/rice/MemoryView.ipp +3 -0
  42. data/rice/Return.hpp +7 -27
  43. data/rice/Return.ipp +13 -13
  44. data/rice/cpp_api/Array.hpp +209 -0
  45. data/rice/cpp_api/Array.ipp +304 -0
  46. data/rice/cpp_api/Builtin_Object.hpp +31 -0
  47. data/rice/cpp_api/Builtin_Object.ipp +37 -0
  48. data/rice/cpp_api/Class.hpp +70 -0
  49. data/rice/cpp_api/Class.ipp +97 -0
  50. data/rice/cpp_api/Encoding.hpp +32 -0
  51. data/rice/cpp_api/Encoding.ipp +59 -0
  52. data/rice/cpp_api/Hash.hpp +194 -0
  53. data/rice/cpp_api/Hash.ipp +257 -0
  54. data/rice/{Identifier.hpp → cpp_api/Identifier.hpp} +2 -6
  55. data/rice/{Identifier.ipp → cpp_api/Identifier.ipp} +4 -2
  56. data/rice/cpp_api/Module.hpp +72 -0
  57. data/rice/cpp_api/Module.ipp +101 -0
  58. data/rice/cpp_api/Object.hpp +272 -0
  59. data/rice/cpp_api/Object.ipp +235 -0
  60. data/rice/cpp_api/String.hpp +74 -0
  61. data/rice/cpp_api/String.ipp +120 -0
  62. data/rice/cpp_api/Struct.hpp +113 -0
  63. data/rice/cpp_api/Struct.ipp +92 -0
  64. data/rice/cpp_api/Symbol.hpp +46 -0
  65. data/rice/cpp_api/Symbol.ipp +93 -0
  66. data/rice/cpp_api/shared_methods.hpp +134 -0
  67. data/rice/detail/DefaultHandler.hpp +12 -0
  68. data/rice/detail/DefaultHandler.ipp +8 -0
  69. data/rice/detail/HandlerRegistry.hpp +5 -35
  70. data/rice/detail/HandlerRegistry.ipp +7 -11
  71. data/rice/detail/InstanceRegistry.hpp +1 -4
  72. data/rice/detail/MethodInfo.hpp +12 -10
  73. data/rice/detail/MethodInfo.ipp +26 -21
  74. data/rice/detail/Native.hpp +33 -0
  75. data/rice/detail/Native.ipp +157 -0
  76. data/rice/detail/NativeAttributeGet.hpp +52 -0
  77. data/rice/detail/NativeAttributeGet.ipp +57 -0
  78. data/rice/detail/NativeAttributeSet.hpp +44 -0
  79. data/rice/detail/NativeAttributeSet.ipp +88 -0
  80. data/rice/detail/NativeCallbackFFI.hpp +55 -0
  81. data/rice/detail/NativeCallbackFFI.ipp +151 -0
  82. data/rice/detail/NativeCallbackSimple.hpp +30 -0
  83. data/rice/detail/NativeCallbackSimple.ipp +29 -0
  84. data/rice/detail/NativeFunction.hpp +33 -23
  85. data/rice/detail/NativeFunction.ipp +309 -70
  86. data/rice/detail/NativeIterator.hpp +9 -11
  87. data/rice/detail/NativeIterator.ipp +33 -31
  88. data/rice/detail/NativeRegistry.hpp +24 -15
  89. data/rice/detail/NativeRegistry.ipp +23 -48
  90. data/rice/detail/Proc.hpp +4 -0
  91. data/rice/detail/Proc.ipp +85 -0
  92. data/rice/detail/Registries.hpp +0 -7
  93. data/rice/detail/Registries.ipp +0 -18
  94. data/rice/detail/RubyFunction.hpp +0 -3
  95. data/rice/detail/RubyFunction.ipp +4 -8
  96. data/rice/detail/RubyType.hpp +16 -0
  97. data/rice/detail/RubyType.ipp +232 -0
  98. data/rice/detail/Type.hpp +7 -6
  99. data/rice/detail/Type.ipp +192 -45
  100. data/rice/detail/TypeRegistry.hpp +15 -7
  101. data/rice/detail/TypeRegistry.ipp +105 -12
  102. data/rice/detail/Wrapper.hpp +68 -32
  103. data/rice/detail/Wrapper.ipp +121 -109
  104. data/rice/detail/cpp_protect.hpp +5 -6
  105. data/rice/detail/default_allocation_func.ipp +0 -2
  106. data/rice/detail/from_ruby.hpp +38 -3
  107. data/rice/detail/from_ruby.ipp +1321 -492
  108. data/rice/detail/ruby.hpp +18 -0
  109. data/rice/detail/to_ruby.hpp +41 -3
  110. data/rice/detail/to_ruby.ipp +1424 -194
  111. data/rice/global_function.hpp +0 -4
  112. data/rice/global_function.ipp +0 -1
  113. data/rice/libc/file.hpp +11 -0
  114. data/rice/libc/file.ipp +32 -0
  115. data/rice/rice.hpp +116 -26
  116. data/rice/ruby_mark.hpp +4 -3
  117. data/rice/stl/complex.hpp +6 -0
  118. data/rice/stl/complex.ipp +93 -0
  119. data/rice/stl/exception.hpp +11 -0
  120. data/rice/stl/exception.ipp +29 -0
  121. data/rice/stl/exception_ptr.hpp +6 -0
  122. data/rice/stl/exception_ptr.ipp +27 -0
  123. data/rice/stl/map.hpp +12 -0
  124. data/rice/stl/map.ipp +469 -0
  125. data/rice/stl/monostate.hpp +6 -0
  126. data/rice/stl/monostate.ipp +80 -0
  127. data/rice/stl/multimap.hpp +14 -0
  128. data/rice/stl/multimap.ipp +448 -0
  129. data/rice/stl/optional.hpp +6 -0
  130. data/rice/stl/optional.ipp +118 -0
  131. data/rice/stl/pair.hpp +13 -0
  132. data/rice/stl/pair.ipp +155 -0
  133. data/rice/stl/reference_wrapper.hpp +6 -0
  134. data/rice/stl/reference_wrapper.ipp +41 -0
  135. data/rice/stl/set.hpp +12 -0
  136. data/rice/stl/set.ipp +495 -0
  137. data/rice/stl/shared_ptr.hpp +28 -0
  138. data/rice/stl/shared_ptr.ipp +224 -0
  139. data/rice/stl/string.hpp +6 -0
  140. data/rice/stl/string.ipp +158 -0
  141. data/rice/stl/string_view.hpp +6 -0
  142. data/rice/stl/string_view.ipp +65 -0
  143. data/rice/stl/tuple.hpp +6 -0
  144. data/rice/stl/tuple.ipp +128 -0
  145. data/rice/stl/type_index.hpp +6 -0
  146. data/rice/stl/type_index.ipp +30 -0
  147. data/rice/stl/type_info.hpp +6 -0
  148. data/rice/stl/type_info.ipp +29 -0
  149. data/rice/stl/unique_ptr.hpp +22 -0
  150. data/rice/stl/unique_ptr.ipp +139 -0
  151. data/rice/stl/unordered_map.hpp +12 -0
  152. data/rice/stl/unordered_map.ipp +469 -0
  153. data/rice/stl/variant.hpp +6 -0
  154. data/rice/stl/variant.ipp +242 -0
  155. data/rice/stl/vector.hpp +12 -0
  156. data/rice/stl/vector.ipp +590 -0
  157. data/rice/stl.hpp +11 -3
  158. data/rice/traits/attribute_traits.hpp +26 -0
  159. data/rice/traits/function_traits.hpp +95 -0
  160. data/rice/traits/method_traits.hpp +47 -0
  161. data/rice/traits/rice_traits.hpp +160 -0
  162. data/rice.gemspec +85 -0
  163. data/test/embed_ruby.cpp +7 -1
  164. data/test/extconf.rb +2 -0
  165. data/test/test_Address_Registration_Guard.cpp +5 -0
  166. data/test/test_Array.cpp +18 -4
  167. data/test/test_Attribute.cpp +136 -21
  168. data/test/test_Buffer.cpp +285 -0
  169. data/test/test_Builtin_Object.cpp +5 -0
  170. data/test/test_Callback.cpp +230 -0
  171. data/test/test_Class.cpp +5 -31
  172. data/test/test_Constructor.cpp +69 -6
  173. data/test/test_Data_Object.cpp +97 -38
  174. data/test/test_Data_Type.cpp +470 -65
  175. data/test/test_Director.cpp +17 -8
  176. data/test/test_Enum.cpp +155 -40
  177. data/test/test_Exception.cpp +235 -0
  178. data/test/test_File.cpp +70 -0
  179. data/test/test_From_Ruby.cpp +609 -0
  180. data/test/test_Hash.cpp +5 -0
  181. data/test/test_Identifier.cpp +5 -0
  182. data/test/test_Inheritance.cpp +6 -1
  183. data/test/test_Iterator.cpp +6 -1
  184. data/test/test_Jump_Exception.cpp +23 -0
  185. data/test/test_Keep_Alive.cpp +13 -19
  186. data/test/test_Keep_Alive_No_Wrapper.cpp +5 -1
  187. data/test/test_Memory_Management.cpp +5 -0
  188. data/test/test_Module.cpp +128 -67
  189. data/test/test_Native_Registry.cpp +2 -34
  190. data/test/test_Object.cpp +5 -0
  191. data/test/test_Overloads.cpp +806 -0
  192. data/test/test_Ownership.cpp +160 -54
  193. data/test/test_Proc.cpp +44 -0
  194. data/test/test_Self.cpp +9 -4
  195. data/test/test_Stl_Exception.cpp +109 -0
  196. data/test/test_Stl_Map.cpp +54 -42
  197. data/test/test_Stl_Multimap.cpp +693 -0
  198. data/test/test_Stl_Optional.cpp +5 -0
  199. data/test/test_Stl_Pair.cpp +14 -9
  200. data/test/test_Stl_Reference_Wrapper.cpp +9 -2
  201. data/test/test_Stl_Set.cpp +790 -0
  202. data/test/test_Stl_SharedPtr.cpp +458 -0
  203. data/test/test_Stl_String.cpp +5 -0
  204. data/test/test_Stl_String_View.cpp +5 -0
  205. data/test/test_Stl_Tuple.cpp +116 -0
  206. data/test/test_Stl_Type.cpp +147 -0
  207. data/test/test_Stl_UniquePtr.cpp +202 -0
  208. data/test/test_Stl_Unordered_Map.cpp +43 -38
  209. data/test/test_Stl_Variant.cpp +217 -84
  210. data/test/test_Stl_Vector.cpp +306 -58
  211. data/test/test_String.cpp +5 -0
  212. data/test/test_Struct.cpp +5 -0
  213. data/test/test_Symbol.cpp +5 -0
  214. data/test/test_Template.cpp +192 -0
  215. data/test/test_To_Ruby.cpp +524 -0
  216. data/test/test_Tracking.cpp +1 -0
  217. data/test/test_Type.cpp +171 -0
  218. data/test/test_global_functions.cpp +67 -7
  219. data/test/unittest.cpp +8 -0
  220. metadata +127 -26
  221. data/lib/version.rb +0 -3
  222. data/rice/Address_Registration_Guard_defn.hpp +0 -79
  223. data/rice/Data_Object_defn.hpp +0 -84
  224. data/rice/Data_Type_defn.hpp +0 -190
  225. data/rice/Exception_defn.hpp +0 -68
  226. data/rice/HandlerRegistration.hpp +0 -15
  227. data/rice/detail/ExceptionHandler.hpp +0 -8
  228. data/rice/detail/ExceptionHandler.ipp +0 -28
  229. data/rice/detail/ExceptionHandler_defn.hpp +0 -77
  230. data/rice/detail/Jump_Tag.hpp +0 -21
  231. data/rice/detail/NativeAttribute.hpp +0 -64
  232. data/rice/detail/NativeAttribute.ipp +0 -112
  233. data/rice/detail/from_ruby_defn.hpp +0 -38
  234. data/rice/detail/to_ruby_defn.hpp +0 -48
  235. data/test/test_Jump_Tag.cpp +0 -17
  236. data/test/test_Stl_SmartPointer.cpp +0 -283
  237. data/test/test_To_From_Ruby.cpp +0 -399
@@ -0,0 +1,693 @@
1
+ #include <complex>
2
+ #include <memory>
3
+
4
+ #include "unittest.hpp"
5
+ #include "embed_ruby.hpp"
6
+ #include <rice/rice.hpp>
7
+ #include <rice/stl.hpp>
8
+ #include <ruby/version.h>
9
+
10
+ using namespace Rice;
11
+
12
+ TESTSUITE(Multimap);
13
+
14
+ SETUP(Multimap)
15
+ {
16
+ embed_ruby();
17
+ }
18
+
19
+ TEARDOWN(Multimap)
20
+ {
21
+ rb_gc_start();
22
+ }
23
+
24
+ namespace
25
+ {
26
+ class MyClass
27
+ {
28
+ public:
29
+ std::multimap<std::string, std::string> stringMultimap()
30
+ {
31
+ std::multimap<std::string, std::string> result{ {"One", "1"}, {"Two", "2"}, {"Three", "3"} };
32
+ return result;
33
+ }
34
+ };
35
+ }
36
+
37
+ Class makeMultimapClass()
38
+ {
39
+ Class c = define_class<MyClass>("MyClass").
40
+ define_constructor(Constructor<MyClass>()).
41
+ define_method("stringMultimap", &MyClass::stringMultimap);
42
+
43
+ return c;
44
+ }
45
+
46
+ TESTCASE(StringMultimap)
47
+ {
48
+ Module m = define_module("Testing");
49
+
50
+ Class c = define_multimap<std::string, std::string>("StringMultimap");
51
+
52
+ Object multimap = m.module_eval("$multimap = Std::StringMultimap.new");
53
+ Object result = multimap.call("size");
54
+ ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
55
+
56
+ m.module_eval("$multimap.insert('a_key', 'a_value')");
57
+ result = multimap.call("size");
58
+ ASSERT_EQUAL(1, detail::From_Ruby<int32_t>().convert(result));
59
+
60
+ m.module_eval("$multimap.clear");
61
+ result = multimap.call("size");
62
+ ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
63
+ }
64
+
65
+ TESTCASE(WrongType)
66
+ {
67
+ Module m = define_module("Testing");
68
+
69
+ Class c = define_multimap<std::string, std::string>("StringMultimap");
70
+ Object multimap = m.module_eval("$multimap = Std::StringMultimap.new");
71
+
72
+ ASSERT_EXCEPTION_CHECK(
73
+ Exception,
74
+ m.module_eval("$multimap.insert(1, 'abc')"),
75
+ ASSERT_EQUAL("wrong argument type Integer (expected String)", ex.what()));
76
+
77
+ ASSERT_EXCEPTION_CHECK(
78
+ Exception,
79
+ m.module_eval("$multimap.insert('abc', true)"),
80
+ ASSERT_EQUAL("wrong argument type true (expected String)", ex.what()));
81
+ }
82
+
83
+ TESTCASE(Empty)
84
+ {
85
+ Module m = define_module("Testing");
86
+
87
+ Class c = define_multimap<std::string, std::int32_t>("IntMultimap");
88
+ Object multimap = c.call("new");
89
+
90
+ Object result = multimap.call("size");
91
+ ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
92
+
93
+ result = multimap.call("empty?");
94
+ ASSERT_EQUAL(Qtrue, result.value());
95
+ }
96
+
97
+ TESTCASE(Include)
98
+ {
99
+ Module m = define_module("Testing");
100
+
101
+ Class c = define_multimap<std::string, std::int32_t>("IntMultimap");
102
+ Object multimap = c.call("new");
103
+ multimap.call("insert", "one", 1);
104
+ multimap.call("insert", "two", 2);
105
+
106
+ Object result = multimap.call("include?", "two");
107
+ ASSERT_EQUAL(Qtrue, result.value());
108
+
109
+ result = multimap.call("include?", "three");
110
+ ASSERT_EQUAL(Qfalse, result.value());
111
+
112
+ Array array = multimap.call("[]", "three");
113
+ ASSERT_EQUAL(0, array.size());
114
+ }
115
+
116
+ TESTCASE(Value)
117
+ {
118
+ Module m = define_module("Testing");
119
+
120
+ Class c = define_multimap<std::string, std::int32_t>("IntMultimap");
121
+ Object multimap = c.call("new");
122
+ multimap.call("insert", "one", 1);
123
+ multimap.call("insert", "two", 2);
124
+
125
+ Object result = multimap.call("value?", 2);
126
+ ASSERT_EQUAL(Qtrue, result.value());
127
+
128
+ result = multimap.call("value?", 4);
129
+ ASSERT_EQUAL(Qfalse, result.value());
130
+ }
131
+
132
+ TESTCASE(ToString)
133
+ {
134
+ Module m = define_module("Testing");
135
+
136
+ Class c = define_multimap<std::string, std::int32_t>("IntMultimap");
137
+ Object multimap = c.call("new");
138
+ multimap.call("insert", "one", 1);
139
+ multimap.call("insert", "two", 2);
140
+
141
+ Object result = multimap.call("to_s");
142
+ ASSERT_EQUAL("<Multimap≺string‚ int≻:{one => 1, two => 2}>", detail::From_Ruby<std::string>().convert(result));
143
+
144
+ multimap.call("clear");
145
+
146
+ result = multimap.call("to_s");
147
+ ASSERT_EQUAL("<Multimap≺string‚ int≻:{}>", detail::From_Ruby<std::string>().convert(result));
148
+ }
149
+
150
+ TESTCASE(Update)
151
+ {
152
+ Module m = define_module("Testing");
153
+
154
+ Class c = define_multimap<std::string, std::string>("StringMultimap");
155
+ Object multimap = c.call("new");
156
+ multimap.call("insert", "one", "original 1");
157
+ multimap.call("insert", "two", "original 2");
158
+
159
+ Object result = multimap.call("size");
160
+ ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
161
+
162
+ result = multimap.call("insert", "two", "new 2");
163
+ ASSERT_EQUAL("new 2", detail::From_Ruby<std::string>().convert(result));
164
+
165
+ result = multimap.call("size");
166
+ ASSERT_EQUAL(3, detail::From_Ruby<int32_t>().convert(result));
167
+
168
+ Array array = multimap.call("[]", "two");
169
+ ASSERT_EQUAL(2, array.size());
170
+ ASSERT_EQUAL("original 2", String(array[0]).c_str());
171
+ ASSERT_EQUAL("new 2", String(array[1]).c_str());
172
+ }
173
+
174
+ TESTCASE(Modify)
175
+ {
176
+ Module m = define_module("Testing");
177
+
178
+ Class c = define_multimap<std::string, int64_t>("Int64Multimap");
179
+ Object multimap = c.call("new");
180
+
181
+ Object result = multimap.call("insert", "one", 3232323232);
182
+
183
+ result = multimap.call("size");
184
+ ASSERT_EQUAL(1, detail::From_Ruby<int32_t>().convert(result));
185
+
186
+ result = multimap.call("delete", "one");
187
+ ASSERT_EQUAL(3232323232, detail::From_Ruby<int64_t>().convert(result));
188
+
189
+ result = multimap.call("size");
190
+ ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
191
+ }
192
+
193
+ TESTCASE(keysAndValues)
194
+ {
195
+ Module m = define_module("Testing");
196
+
197
+ Class c = define_multimap<std::string, int32_t>("Int32Multimap");
198
+ Object multimap = c.call("new");
199
+
200
+ multimap.call("insert", "one", 1);
201
+ multimap.call("insert", "two", 2);
202
+ multimap.call("insert", "three", 3);
203
+
204
+ // Keys returns a std::vector
205
+ Data_Object<std::vector<std::string>> keys = multimap.call("keys");
206
+ std::vector<std::string> expected_keys{ {"one", "three", "two"} };
207
+ ASSERT_EQUAL(3u, keys->size());
208
+ ASSERT_EQUAL(expected_keys[0], keys->operator[](0));
209
+ ASSERT_EQUAL(expected_keys[1], keys->operator[](1));
210
+ ASSERT_EQUAL(expected_keys[2], keys->operator[](2));
211
+
212
+ // Keys returns a std::vector
213
+ Data_Object<std::vector<std::int32_t>> values = multimap.call("values");
214
+ std::vector<std::int32_t> expected_values{ {1, 3, 2} };
215
+ ASSERT_EQUAL(3u, values->size());
216
+ ASSERT_EQUAL(expected_values[0], values->operator[](0));
217
+ ASSERT_EQUAL(expected_values[1], values->operator[](1));
218
+ ASSERT_EQUAL(expected_values[2], values->operator[](2));
219
+ }
220
+
221
+ TESTCASE(Copy)
222
+ {
223
+ Module m = define_module("Testing");
224
+
225
+ Class c = define_multimap<std::string, double>("DoubleMultimap");
226
+ Object object = c.call("new");
227
+
228
+ object.call("insert", "one", 11.1);
229
+ object.call("insert", "two", 22.2);
230
+ std::multimap<std::string, double>& multimap = detail::From_Ruby<std::multimap<std::string, double>&>().convert(object);
231
+
232
+ Object result = object.call("copy");
233
+ std::multimap<std::string, double>& multimapCopy = detail::From_Ruby<std::multimap<std::string, double>&>().convert(result);
234
+
235
+ ASSERT_EQUAL(multimap, multimapCopy);
236
+ }
237
+
238
+ TESTCASE(Iterate)
239
+ {
240
+ Module m = define_module("Testing");
241
+ Class c = define_multimap<std::string, int>("IntMultimap");
242
+
243
+ std::string code = R"(multimap = Std::IntMultimap.new
244
+ multimap.insert("five", 5)
245
+ multimap.insert("six", 6)
246
+ multimap.insert("seven", 7)
247
+
248
+ result = Hash.new
249
+ multimap.map do |pair|
250
+ result[pair.first] = 2 * pair.second
251
+ end
252
+ result)";
253
+
254
+ Hash result = m.module_eval(code);
255
+ ASSERT_EQUAL(3u, result.size());
256
+
257
+ std::string result_string = result.to_s().str();
258
+ #if RUBY_API_VERSION_MAJOR == 3 && RUBY_API_VERSION_MINOR >= 4
259
+ ASSERT_EQUAL("{\"five\" => 10, \"seven\" => 14, \"six\" => 12}", result_string);
260
+ #else
261
+ ASSERT_EQUAL("{\"five\"=>10, \"seven\"=>14, \"six\"=>12}", result_string);
262
+ #endif
263
+ }
264
+
265
+ TESTCASE(ToEnum)
266
+ {
267
+ Module m = define_module("Testing");
268
+ Class c = define_multimap<std::string, int>("IntMultimap");
269
+
270
+ std::string code = R"(multimap = Std::IntMultimap.new
271
+ multimap.insert("five", 5)
272
+ multimap.insert("six", 6)
273
+ multimap.insert("seven", 7)
274
+
275
+ result = Hash.new
276
+ multimap.each do |pair|
277
+ result[pair.first] = 2 * pair.second
278
+ end
279
+ result)";
280
+
281
+ Hash result = m.module_eval(code);
282
+ ASSERT_EQUAL(3u, result.size());
283
+
284
+ std::string result_string = result.to_s().str();
285
+
286
+ #if RUBY_API_VERSION_MAJOR == 3 && RUBY_API_VERSION_MINOR >= 4
287
+ ASSERT_EQUAL("{\"five\" => 10, \"seven\" => 14, \"six\" => 12}", result_string);
288
+ #else
289
+ ASSERT_EQUAL("{\"five\"=>10, \"seven\"=>14, \"six\"=>12}", result_string);
290
+ #endif
291
+ }
292
+
293
+ TESTCASE(ToEnumSize)
294
+ {
295
+ Module m = define_module("TestingModule");
296
+ Class c = define_multimap<std::string, int>("IntMultimap");
297
+
298
+ std::string code = R"(multimap = Std::IntMultimap.new
299
+ multimap.insert("five", 5)
300
+ multimap.insert("six", 6)
301
+ multimap.insert("seven", 7)
302
+ multimap.insert("eight", 7)
303
+ multimap.insert("eight", 8)
304
+ multimap)";
305
+
306
+ Object multimap = m.module_eval(code);
307
+ Object enumerable = multimap.call("each");
308
+ Object result = enumerable.call("size");
309
+
310
+ ASSERT_EQUAL(5, detail::From_Ruby<int>().convert(result));
311
+ }
312
+
313
+ namespace
314
+ {
315
+ class NotComparable
316
+ {
317
+ public:
318
+ NotComparable(uint32_t value) : value_(value)
319
+ {
320
+ };
321
+
322
+ NotComparable() = default;
323
+
324
+ uint32_t value_;
325
+ };
326
+ }
327
+
328
+ TESTCASE(NotComparable)
329
+ {
330
+ define_class<NotComparable>("NotComparable").
331
+ define_constructor(Constructor<NotComparable, uint32_t>());
332
+
333
+ Class c = define_multimap<std::string, NotComparable>("NotComparableMultimap");
334
+
335
+ Object multimap = c.call("new");
336
+ multimap.call("insert", "one", NotComparable(1));
337
+ multimap.call("insert", "two", NotComparable(2));
338
+ multimap.call("insert", "three", NotComparable(3));
339
+
340
+ Object result = multimap.call("include?", "two");
341
+ ASSERT_EQUAL(Qtrue, result.value());
342
+
343
+ result = multimap.call("value?", NotComparable(3));
344
+ ASSERT_EQUAL(Qfalse, result.value());
345
+ }
346
+
347
+ TESTCASE(NotPrintable)
348
+ {
349
+ define_class<NotComparable>("NotComparable").
350
+ define_constructor(Constructor<NotComparable, uint32_t>());
351
+
352
+ Class c = define_multimap<std::string, NotComparable>("NotComparableMultimap");
353
+
354
+ Object multimap = c.call("new");
355
+ multimap.call("insert", "one", NotComparable(1));
356
+ multimap.call("insert", "two", NotComparable(2));
357
+ multimap.call("insert", "three", NotComparable(3));
358
+
359
+ Object result = multimap.call("to_s");
360
+ ASSERT_EQUAL("[Not printable]", detail::From_Ruby<std::string>().convert(result));
361
+ }
362
+
363
+ namespace
364
+ {
365
+ class Comparable
366
+ {
367
+ public:
368
+ Comparable() = default;
369
+ Comparable(uint32_t value) : value_(value)
370
+ {
371
+ };
372
+
373
+ bool operator==(const Comparable& other) const
374
+ {
375
+ return this->value_ == other.value_;
376
+ }
377
+
378
+ uint32_t value_;
379
+ };
380
+
381
+ inline std::ostream& operator<<(std::ostream& stream, Comparable const& comparable)
382
+ {
383
+ stream << "Comparable(" << std::to_string(comparable.value_) << ")";
384
+ return stream;
385
+ }
386
+ }
387
+
388
+ TESTCASE(Comparable)
389
+ {
390
+ define_class<Comparable>("IsComparable").
391
+ define_constructor(Constructor<Comparable, uint32_t>());
392
+
393
+ Class c = define_multimap<std::string, Comparable>("ComparableMultimap");
394
+
395
+ Object multimap = c.call("new");
396
+
397
+ multimap.call("insert", "one", Comparable(1));
398
+ multimap.call("insert", "two", Comparable(2));
399
+ multimap.call("insert", "three", Comparable(3));
400
+
401
+ Object result = multimap.call("value?", Comparable(2));
402
+ ASSERT_EQUAL(Qtrue, result.value());
403
+ }
404
+
405
+ TESTCASE(Printable)
406
+ {
407
+ define_class<Comparable>("IsComparable").
408
+ define_constructor(Constructor<Comparable, uint32_t>());
409
+
410
+ Class c = define_multimap<std::string, Comparable>("ComparableMultimap");
411
+
412
+ Object multimap = c.call("new");
413
+ multimap.call("insert", "one", Comparable(1));
414
+ multimap.call("insert", "two", Comparable(2));
415
+ multimap.call("insert", "three", Comparable(3));
416
+
417
+ Object result = multimap.call("to_s");
418
+ ASSERT_EQUAL("<Multimap≺string‚ AnonymousNamespace꞉꞉Comparable≻:{one => Comparable(1), three => Comparable(3), two => Comparable(2)}>",
419
+ detail::From_Ruby<std::string>().convert(result));
420
+ }
421
+
422
+ namespace
423
+ {
424
+ std::multimap<std::string, std::complex<double>> returnComplexMultimap()
425
+ {
426
+ std::complex<double> complex1(1, 1);
427
+ std::complex<double> complex2(2, 2);
428
+ std::complex<double> complex3(3, 3);
429
+
430
+ std::multimap<std::string, std::complex<double>> result;
431
+ using Value_T = std::multimap<std::string, std::complex<double>>::value_type;
432
+ result.insert(Value_T{ "one", complex1 });
433
+ result.insert(Value_T{ "two", complex2 });
434
+ result.insert(Value_T{ "three", complex3 });
435
+ return result;
436
+ }
437
+
438
+ std::multimap<std::string, std::complex<double>> passComplexMultimap(std::multimap<std::string, std::complex<double>>& complexes)
439
+ {
440
+ return complexes;
441
+ }
442
+ }
443
+
444
+ TESTCASE(AutoRegisterReturn)
445
+ {
446
+ define_global_function("return_complex_multimap", &returnComplexMultimap);
447
+
448
+ Module m = define_module("Testing");
449
+ Object multimap = m.module_eval("return_complex_multimap");
450
+ ASSERT_EQUAL("Std::Multimap≺string‚ complex≺double≻≻",
451
+ multimap.class_name().str());
452
+
453
+ std::string code = R"(multimap = return_complex_multimap
454
+ complex = multimap['three']
455
+ complex == [Complex(3, 3)])";
456
+
457
+ Object result = m.module_eval(code);
458
+ ASSERT_EQUAL(Qtrue, result.value());
459
+
460
+ // Now register the multimap again
461
+ define_multimap<std::string, std::complex<double>>("ComplexMultimap");
462
+ code = R"(multimap = Std::ComplexMultimap.new)";
463
+ result = m.module_eval(code);
464
+ ASSERT(result.is_instance_of(multimap.class_of()));
465
+
466
+ // And again in the module
467
+ define_multimap<std::string, std::complex<double>>("ComplexMultimap2");
468
+ code = R"(multimap = Std::ComplexMultimap2.new)";
469
+ result = m.module_eval(code);
470
+ ASSERT(result.is_instance_of(multimap.class_of()));
471
+ }
472
+
473
+ TESTCASE(AutoRegisterParameter)
474
+ {
475
+ define_global_function("pass_complex_multimap", &passComplexMultimap);
476
+
477
+ std::string code = R"(multimap = Std::Multimap≺string‚ complex≺double≻≻.new
478
+ multimap.insert("four", Complex(4.0, 4.0))
479
+ multimap.insert("five", Complex(5.0, 5.0))
480
+ pass_complex_multimap(multimap))";
481
+
482
+ Module m = define_module("Testing");
483
+ Object multimap = m.module_eval(code);
484
+
485
+ Object result = multimap.call("size");
486
+ ASSERT_EQUAL("Std::Multimap≺string‚ complex≺double≻≻",
487
+ multimap.class_name().str());
488
+ ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
489
+
490
+ std::multimap<std::string, std::complex<double>> expected{ {"four", std::complex<double>(4, 4)},
491
+ {"five", std::complex<double>(5, 5)} };
492
+
493
+ std::multimap<std::string, std::complex<double>> complexes = detail::From_Ruby<std::multimap<std::string, std::complex<double>>>().convert(multimap);
494
+
495
+ ASSERT_EQUAL(expected, complexes);
496
+ }
497
+
498
+ namespace
499
+ {
500
+ std::multimap<std::string, std::string> defaultMultimap(std::multimap<std::string, std::string> strings = {{"one", "value 1"}, {"two", "value 2"}, {"three", "value 3"}})
501
+ {
502
+ return strings;
503
+ }
504
+ }
505
+
506
+ TESTCASE(DefaultValue)
507
+ {
508
+ define_multimap<std::string, std::string>("StringMultimap");
509
+ define_global_function("default_multimap", &defaultMultimap, Arg("strings") = std::multimap<std::string, std::string>{ {"one", "value 1"}, {"two", "value 2"}, {"three", "value 3"} });
510
+
511
+ Module m = define_module("Testing");
512
+ Object result = m.module_eval("default_multimap");
513
+ std::multimap<std::string, std::string> actual = detail::From_Ruby<std::multimap<std::string, std::string>>().convert(result);
514
+
515
+ std::multimap<std::string, std::string> expected{ {"one", "value 1"}, {"two", "value 2"}, {"three", "value 3"} };
516
+
517
+ ASSERT_EQUAL(expected, actual);
518
+ }
519
+
520
+ namespace
521
+ {
522
+ std::multimap<std::string, int> ints;
523
+ std::multimap<std::string, float> floats;
524
+ std::multimap<std::string, std::string> strings;
525
+
526
+ void hashToMultimap(std::multimap<std::string, int> aInts, std::multimap<std::string, float> aFloats, std::multimap<std::string, std::string> aStrings)
527
+ {
528
+ ints = aInts;
529
+ floats = aFloats;
530
+ strings = aStrings;
531
+ }
532
+
533
+ void hashToMultimapRefs(std::multimap<std::string, int>& aInts, std::multimap<std::string, float>& aFloats, std::multimap<std::string, std::string>& aStrings)
534
+ {
535
+ ints = aInts;
536
+ floats = aFloats;
537
+ strings = aStrings;
538
+ }
539
+
540
+ void hashToMultimapPointers(std::multimap<std::string, int>* aInts, std::multimap<std::string, float>* aFloats, std::multimap<std::string, std::string>* aStrings)
541
+ {
542
+ ints = *aInts;
543
+ floats = *aFloats;
544
+ strings = *aStrings;
545
+ }
546
+ }
547
+
548
+ TESTCASE(HashToMultimap)
549
+ {
550
+ define_global_function("hash_to_multimap", &hashToMultimap);
551
+
552
+ Module m = define_module("Testing");
553
+
554
+ std::string code = R"(hash_to_multimap({"seven" => 7,
555
+ "nine" => 9,
556
+ "million" => 1_000_000},
557
+ {"forty nine" => 49.0,
558
+ "seventy eight" => 78.0,
559
+ "nine hundred ninety nine" => 999.0},
560
+ {"one" => "one",
561
+ "two" => "two",
562
+ "three" => "three"}))";
563
+
564
+ m.module_eval(code);
565
+
566
+ std::multimap<std::string, int> expectedInts{{"seven", 7},
567
+ {"nine", 9},
568
+ {"million", 1000000 } };
569
+ ASSERT_EQUAL(expectedInts, ints);
570
+
571
+ std::multimap<std::string, float> expectedFloats{ {"forty nine", 49.0f},
572
+ {"seventy eight", 78.0f},
573
+ {"nine hundred ninety nine", 999.0f} };
574
+ ASSERT_EQUAL(expectedFloats, floats);
575
+
576
+ std::multimap<std::string, std::string> expectedStrings{ {"one", "one"},
577
+ {"two", "two"},
578
+ {"three", "three"} };
579
+ ASSERT_EQUAL(expectedStrings, strings);
580
+ }
581
+
582
+ TESTCASE(HashToMultimapRefs)
583
+ {
584
+ define_global_function("hash_to_multimap_refs", &hashToMultimapRefs);
585
+
586
+ Module m = define_module("Testing");
587
+
588
+ std::string code = R"(hash_to_multimap_refs({"eight" => 8,
589
+ "ten" => 10,
590
+ "million one" => 1_000_001},
591
+ {"fifty" => 50.0,
592
+ "seventy nine" => 79.0,
593
+ "one thousand" => 1_000.0},
594
+ {"eleven" => "eleven",
595
+ "twelve" => "twelve",
596
+ "thirteen" => "thirteen"}))";
597
+ m.module_eval(code);
598
+
599
+ std::multimap<std::string, int> expectedInts{ {"eight", 8},
600
+ {"ten", 10},
601
+ {"million one", 1000001 } };
602
+ ASSERT_EQUAL(expectedInts, ints);
603
+
604
+ std::multimap<std::string, float> expectedFloats{ {"fifty", 50.0f},
605
+ {"seventy nine", 79.0f},
606
+ {"one thousand", 1000.0f} };
607
+ ASSERT_EQUAL(expectedFloats, floats);
608
+
609
+ std::multimap<std::string, std::string> expectedStrings{ {"eleven", "eleven"},
610
+ {"twelve", "twelve"},
611
+ {"thirteen", "thirteen"} };
612
+ ASSERT_EQUAL(expectedStrings, strings);
613
+ }
614
+
615
+ TESTCASE(HashToMultimapPointers)
616
+ {
617
+ define_global_function("hash_to_multimap_pointers", &hashToMultimapPointers);
618
+
619
+ Module m = define_module("Testing");
620
+
621
+ std::string code = R"(hash_to_multimap_pointers({"nine" => 9,
622
+ "eleven" => 11,
623
+ "million two" => 1_000_002},
624
+ {"fifty one" => 51.0,
625
+ "eighty" => 80.0,
626
+ "one thousand one" => 1_001.0},
627
+ {"fourteen" => "fourteen",
628
+ "fifteen" => "fifteen",
629
+ "sixteen" => "sixteen"}))";
630
+
631
+ m.module_eval(code);
632
+
633
+ std::multimap<std::string, int> expectedInts{ {"nine", 9},
634
+ {"eleven", 11},
635
+ {"million two", 1000002 } };
636
+ ASSERT_EQUAL(expectedInts, ints);
637
+
638
+ std::multimap<std::string, float> expectedFloats{ {"fifty one", 51.0f},
639
+ {"eighty", 80.0f},
640
+ {"one thousand one", 1001.0f} };
641
+ ASSERT_EQUAL(expectedFloats, floats);
642
+
643
+ std::multimap<std::string, std::string> expectedStrings{ {"fourteen", "fourteen"},
644
+ {"fifteen", "fifteen"},
645
+ {"sixteen", "sixteen"} };
646
+ ASSERT_EQUAL(expectedStrings, strings);
647
+ }
648
+
649
+ TESTCASE(HashToMultimapWrongTypes)
650
+ {
651
+ define_global_function("hash_to_multimap", &hashToMultimap);
652
+
653
+ Module m = define_module("Testing");
654
+
655
+ std::string code = R"(hash_to_multimap({"seven" => 7,
656
+ "nine" => 9,
657
+ "million" => 1_000_000},
658
+ {"forty nine" => 49.0,
659
+ "seventy eight" => 78.0,
660
+ "nine hundred ninety nine" => 999.0},
661
+ {"one" => 50.0,
662
+ "two" => 79.0,
663
+ "three" => 1000.0}))";
664
+
665
+ ASSERT_EXCEPTION_CHECK(
666
+ Exception,
667
+ m.module_eval(code),
668
+ ASSERT_EQUAL("wrong argument type Float (expected String)", ex.what())
669
+ );
670
+ }
671
+
672
+ TESTCASE(HashToMultimapMixedTypes)
673
+ {
674
+ define_global_function("hash_to_multimap", &hashToMultimap);
675
+
676
+ Module m = define_module("Testing");
677
+
678
+ std::string code = R"(hash_to_multimap({"seven" => 7,
679
+ "nine" => "nine",
680
+ "million" => true},
681
+ {"forty nine" => 49.0,
682
+ "seventy eight" => 78.0,
683
+ "nine hundred ninety nine" => 999.0},
684
+ {"one" => "one",
685
+ "two" => "two",
686
+ "three" => "three"}))";
687
+
688
+ ASSERT_EXCEPTION_CHECK(
689
+ Exception,
690
+ m.module_eval(code),
691
+ ASSERT_EQUAL("no implicit conversion of String into Integer", ex.what())
692
+ );
693
+ }
@@ -50,6 +50,11 @@ SETUP(Optional)
50
50
  makeOptionalClass();
51
51
  }
52
52
 
53
+ TEARDOWN(Optional)
54
+ {
55
+ rb_gc_start();
56
+ }
57
+
53
58
  TESTCASE(OptionalReturn)
54
59
  {
55
60
  Module m = define_module("Testing");