rice 4.2.1 → 4.3.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.
@@ -1,290 +1,356 @@
1
- #include "unittest.hpp"
2
- #include "embed_ruby.hpp"
3
- #include <rice/rice.hpp>
4
-
5
- using namespace Rice;
6
-
7
- TESTSUITE(Iterator);
8
-
9
- SETUP(Iterator)
10
- {
11
- embed_ruby();
12
- }
13
-
14
- namespace
15
- {
16
- class Container
17
- {
18
- public:
19
- Container(int* array, size_t length)
20
- : array_(array)
21
- , length_(length)
22
- {
23
- }
24
-
25
- // Custom names to make sure we call the function pointers rather than
26
- // expectable default names.
27
- int* beginFoo() { return array_; }
28
- int* endBar() { return array_ + length_; }
29
-
30
- private:
31
- int* array_;
32
- size_t length_;
33
- };
34
- } // namespace
35
-
36
- TESTCASE(define_array_iterator)
37
- {
38
- define_class<Container>("Container")
39
- .define_constructor(Constructor<Container, int*, size_t>())
40
- .define_iterator(&Container::beginFoo, &Container::endBar);
41
-
42
- int array[] = { 1, 2, 3 };
43
- Container* container = new Container(array, 3);
44
-
45
- Object wrapped_container = Data_Object<Container>(container);
46
-
47
- Array a = wrapped_container.instance_eval("a = []; each() { |x| a << x }; a");
48
- ASSERT_EQUAL(3u, a.size());
49
- ASSERT_EQUAL(Object(detail::to_ruby(1)), a[0]);
50
- ASSERT_EQUAL(Object(detail::to_ruby(2)), a[1]);
51
- ASSERT_EQUAL(Object(detail::to_ruby(3)), a[2]);
52
- }
53
-
54
- namespace
55
- {
56
- struct Data
57
- {
58
- Data(uint32_t value)
59
- {
60
- this->index = value;
61
- }
62
-
63
- uint32_t index;
64
- };
65
-
66
- class ContainerValues
67
- {
68
- public:
69
- ContainerValues()
70
- {
71
- this->data_ = { {1}, {2}, {3}};
72
- }
73
-
74
- std::vector<Data>::iterator begin()
75
- {
76
- return this->data_.begin();
77
- }
78
-
79
- std::vector<Data>::iterator end()
80
- {
81
- return this->data_.end();
82
- }
83
-
84
- std::vector<Data>::const_iterator cbegin() const
85
- {
86
- return this->data_.cbegin();
87
- }
88
-
89
- std::vector<Data>::const_iterator cend() const
90
- {
91
- return this->data_.cend();
92
- }
93
-
94
- std::vector<Data> data_;
95
- };
96
-
97
- class ContainerPointers
98
- {
99
- public:
100
- ContainerPointers()
101
- {
102
- this->data_ = { new Data{1}, new Data{2}, new Data{3} };
103
- }
104
-
105
- ~ContainerPointers()
106
- {
107
- for (Data* data : this->data_)
108
- {
109
- delete data;
110
- }
111
- }
112
-
113
- std::vector<Data*>::iterator begin()
114
- {
115
- return this->data_.begin();
116
- }
117
-
118
- std::vector<Data*>::iterator end()
119
- {
120
- return this->data_.end();
121
- }
122
-
123
- std::vector<Data*>::reverse_iterator rbegin()
124
- {
125
- return this->data_.rbegin();
126
- }
127
-
128
- std::vector<Data*>::reverse_iterator rend()
129
- {
130
- return this->data_.rend();
131
- }
132
-
133
- std::vector<Data*> data_;
134
- };
135
- }
136
-
137
- template <>
138
- struct detail::To_Ruby<Data>
139
- {
140
- static VALUE convert(const Data& data)
141
- {
142
- return detail::to_ruby(data.index);
143
- }
144
- };
145
-
146
- template <>
147
- struct detail::To_Ruby<Data*>
148
- {
149
- static VALUE convert(const Data* data)
150
- {
151
- return detail::to_ruby(data->index);
152
- }
153
- };
154
-
155
- TESTCASE(iterator_value)
156
- {
157
- define_class<ContainerValues>("ContainerValues")
158
- .define_constructor(Constructor<ContainerValues>())
159
- .define_iterator(&ContainerValues::begin, &ContainerValues::end);
160
-
161
- ContainerValues* container = new ContainerValues();
162
- Object wrapper = Data_Object<ContainerValues>(container);
163
-
164
- Array a = wrapper.instance_eval("a = []; each() { |x| a << x }; a");
165
- ASSERT_EQUAL(3u, a.size());
166
-
167
- ASSERT_EQUAL(Object(detail::to_ruby(1)), a[0]);
168
- ASSERT_EQUAL(Object(detail::to_ruby(2)), a[1]);
169
- ASSERT_EQUAL(Object(detail::to_ruby(3)), a[2]);
170
- }
171
-
172
- TESTCASE(const_iterator_value)
173
- {
174
- define_class<ContainerValues>("ContainerValues")
175
- .define_constructor(Constructor<ContainerValues>())
176
- .define_iterator(&ContainerValues::cbegin, &ContainerValues::cend);
177
-
178
- Module m = define_module("TestingModule");
179
-
180
- std::string code = R"(result = []
181
- container = ContainerValues.new
182
- container.each do |x|
183
- result << x
184
- end
185
- result)";
186
-
187
- Array result = m.module_eval(code);
188
-
189
- ASSERT_EQUAL(3u, result.size());
190
- ASSERT_EQUAL(Object(detail::to_ruby(1)), result[0]);
191
- ASSERT_EQUAL(Object(detail::to_ruby(2)), result[1]);
192
- ASSERT_EQUAL(Object(detail::to_ruby(3)), result[2]);
193
- }
194
-
195
- TESTCASE(iterator_pointer)
196
- {
197
- define_class<ContainerPointers>("ContainerPointers")
198
- .define_constructor(Constructor<ContainerPointers>())
199
- .define_iterator(&ContainerPointers::begin, &ContainerPointers::end);
200
-
201
- ContainerPointers* container = new ContainerPointers();
202
- Object wrapper = Data_Object<ContainerPointers>(container);
203
-
204
- Module m = define_module("TestingModule");
205
-
206
- std::string code = R"(result = []
207
- container = ContainerPointers.new
208
- container.each do |x|
209
- result << x
210
- end
211
- result)";
212
-
213
- Array result = m.module_eval(code);
214
-
215
- ASSERT_EQUAL(3u, result.size());
216
- ASSERT_EQUAL(Object(detail::to_ruby(1)), result[0]);
217
- ASSERT_EQUAL(Object(detail::to_ruby(2)), result[1]);
218
- ASSERT_EQUAL(Object(detail::to_ruby(3)), result[2]);
219
- }
220
-
221
- TESTCASE(two_iterator_pointer)
222
- {
223
- define_class<ContainerPointers>("ContainerPointers")
224
- .define_constructor(Constructor<ContainerPointers>())
225
- .define_iterator(&ContainerPointers::begin, &ContainerPointers::end)
226
- .define_iterator(&ContainerPointers::rbegin, &ContainerPointers::rend, "reach");
227
-
228
- ContainerPointers* container = new ContainerPointers();
229
- Object wrapper = Data_Object<ContainerPointers>(container);
230
-
231
- Module m = define_module("TestingModule");
232
-
233
- std::string code = R"(result = []
234
- container = ContainerPointers.new
235
- container.each do |x|
236
- result << x
237
- end
238
- container.reach do |x|
239
- result << x
240
- end
241
- result)";
242
-
243
- Array result = m.module_eval(code);
244
-
245
- ASSERT_EQUAL(6u, result.size());
246
- ASSERT_EQUAL(Object(detail::to_ruby(1)), result[0]);
247
- ASSERT_EQUAL(Object(detail::to_ruby(2)), result[1]);
248
- ASSERT_EQUAL(Object(detail::to_ruby(3)), result[2]);
249
- ASSERT_EQUAL(Object(detail::to_ruby(3)), result[3]);
250
- ASSERT_EQUAL(Object(detail::to_ruby(2)), result[4]);
251
- ASSERT_EQUAL(Object(detail::to_ruby(1)), result[5]);
252
- }
253
-
254
- TESTCASE(map)
255
- {
256
- define_class<ContainerPointers>("ContainerPointers")
257
- .define_constructor(Constructor<ContainerPointers>())
258
- .define_iterator(&ContainerPointers::begin, &ContainerPointers::end);
259
-
260
- Module m = define_module("Testing");
261
-
262
- std::string code = R"(container = ContainerPointers.new
263
- container.map do |x|
264
- x * 2
265
- end)";
266
-
267
- Array result = m.module_eval(code);
268
-
269
- ASSERT_EQUAL(3u, result.size());
270
- ASSERT_EQUAL(Object(detail::to_ruby(2)), result[0]);
271
- ASSERT_EQUAL(Object(detail::to_ruby(4)), result[1]);
272
- ASSERT_EQUAL(Object(detail::to_ruby(6)), result[2]);
273
- }
274
-
275
- TESTCASE(to_enum)
276
- {
277
- Module m = define_module("TestingModule");
278
-
279
- std::string code = R"(container = ContainerPointers.new
280
- container.each.map do |x|
281
- x * 2
282
- end)";
283
-
284
- Array result = m.module_eval(code);
285
-
286
- ASSERT_EQUAL(3u, result.size());
287
- ASSERT_EQUAL(Object(detail::to_ruby(2)), result[0]);
288
- ASSERT_EQUAL(Object(detail::to_ruby(4)), result[1]);
289
- ASSERT_EQUAL(Object(detail::to_ruby(6)), result[2]);
290
- }
1
+ #include "unittest.hpp"
2
+ #include "embed_ruby.hpp"
3
+ #include <rice/rice.hpp>
4
+
5
+ using namespace Rice;
6
+
7
+ TESTSUITE(Iterator);
8
+
9
+ SETUP(Iterator)
10
+ {
11
+ embed_ruby();
12
+ }
13
+
14
+ namespace
15
+ {
16
+ class Container
17
+ {
18
+ public:
19
+ Container(int* array, size_t length)
20
+ : array_(array)
21
+ , length_(length)
22
+ {
23
+ }
24
+
25
+ // Custom names to make sure we call the function pointers rather than
26
+ // expectable default names.
27
+ int* beginFoo() { return array_; }
28
+ int* endBar() { return array_ + length_; }
29
+
30
+ private:
31
+ int* array_;
32
+ size_t length_;
33
+ };
34
+ } // namespace
35
+
36
+ TESTCASE(define_array_iterator)
37
+ {
38
+ define_class<Container>("Container")
39
+ .define_constructor(Constructor<Container, int*, size_t>())
40
+ .define_iterator(&Container::beginFoo, &Container::endBar);
41
+
42
+ int array[] = { 1, 2, 3 };
43
+ Container* container = new Container(array, 3);
44
+
45
+ Object wrapped_container = Data_Object<Container>(container);
46
+
47
+ Array a = wrapped_container.instance_eval("a = []; each() { |x| a << x }; a");
48
+ ASSERT_EQUAL(3u, a.size());
49
+ ASSERT_EQUAL(Object(detail::to_ruby(1)), a[0]);
50
+ ASSERT_EQUAL(Object(detail::to_ruby(2)), a[1]);
51
+ ASSERT_EQUAL(Object(detail::to_ruby(3)), a[2]);
52
+ }
53
+
54
+ namespace
55
+ {
56
+ struct Data
57
+ {
58
+ Data(uint32_t value)
59
+ {
60
+ this->index = value;
61
+ }
62
+
63
+ uint32_t index;
64
+ };
65
+
66
+ class ContainerValues
67
+ {
68
+ public:
69
+ ContainerValues()
70
+ {
71
+ this->data_ = { {1}, {2}, {3} };
72
+ }
73
+
74
+ std::vector<Data>::iterator begin()
75
+ {
76
+ return this->data_.begin();
77
+ }
78
+
79
+ std::vector<Data>::iterator end()
80
+ {
81
+ return this->data_.end();
82
+ }
83
+
84
+ std::vector<Data>::const_iterator cbegin() const
85
+ {
86
+ return this->data_.cbegin();
87
+ }
88
+
89
+ std::vector<Data>::const_iterator cend() const
90
+ {
91
+ return this->data_.cend();
92
+ }
93
+
94
+ std::vector<Data> data_;
95
+ };
96
+
97
+ class ContainerPointers
98
+ {
99
+ public:
100
+ ContainerPointers()
101
+ {
102
+ this->data_ = { new Data{1}, new Data{2}, new Data{3} };
103
+ }
104
+
105
+ ~ContainerPointers()
106
+ {
107
+ for (Data* data : this->data_)
108
+ {
109
+ delete data;
110
+ }
111
+ }
112
+
113
+ std::vector<Data*>::iterator begin()
114
+ {
115
+ return this->data_.begin();
116
+ }
117
+
118
+ std::vector<Data*>::iterator end()
119
+ {
120
+ return this->data_.end();
121
+ }
122
+
123
+ std::vector<Data*>::reverse_iterator rbegin()
124
+ {
125
+ return this->data_.rbegin();
126
+ }
127
+
128
+ std::vector<Data*>::reverse_iterator rend()
129
+ {
130
+ return this->data_.rend();
131
+ }
132
+
133
+ std::vector<Data*> data_;
134
+ };
135
+ }
136
+
137
+ TESTCASE(iterator_value)
138
+ {
139
+ define_class<Data>("Data")
140
+ .define_constructor(Constructor<Data, uint32_t>());
141
+
142
+ define_class<ContainerValues>("ContainerValues")
143
+ .define_constructor(Constructor<ContainerValues>())
144
+ .define_iterator(&ContainerValues::begin, &ContainerValues::end);
145
+
146
+ ContainerValues* container = new ContainerValues();
147
+ Data_Object<ContainerValues> wrapper(container);
148
+
149
+ Array a = wrapper.instance_eval("each.to_a");
150
+ ASSERT_EQUAL(3u, a.size());
151
+
152
+ Data_Object<Data> wrappedData(a[0]);
153
+ ASSERT_EQUAL(1, wrappedData->index);
154
+
155
+ wrappedData = (Data_Object<Data>)a[1];
156
+ ASSERT_EQUAL(2, wrappedData->index);
157
+
158
+ wrappedData = (Data_Object<Data>)a[2];
159
+ ASSERT_EQUAL(3, wrappedData->index);
160
+ }
161
+
162
+ TESTCASE(const_iterator_value)
163
+ {
164
+ define_class<Data>("Data")
165
+ .define_constructor(Constructor<Data, uint32_t>());
166
+
167
+ define_class<ContainerValues>("ContainerValues")
168
+ .define_constructor(Constructor<ContainerValues>())
169
+ .define_iterator(&ContainerValues::cbegin, &ContainerValues::cend);
170
+
171
+ Module m = define_module("TestingModule");
172
+
173
+ std::string code = R"(result = []
174
+ container = ContainerValues.new
175
+ container.each do |x|
176
+ result << x
177
+ end
178
+ result)";
179
+
180
+ Array a = m.module_eval(code);
181
+
182
+ Data_Object<Data> wrappedData(a[0]);
183
+ ASSERT_EQUAL(1, wrappedData->index);
184
+
185
+ wrappedData = (Data_Object<Data>)a[1];
186
+ ASSERT_EQUAL(2, wrappedData->index);
187
+
188
+ wrappedData = (Data_Object<Data>)a[2];
189
+ ASSERT_EQUAL(3, wrappedData->index);
190
+ }
191
+
192
+ TESTCASE(iterator_pointer)
193
+ {
194
+ define_class<Data>("Data")
195
+ .define_constructor(Constructor<Data, uint32_t>());
196
+
197
+ define_class<ContainerPointers>("ContainerPointers")
198
+ .define_constructor(Constructor<ContainerPointers>())
199
+ .define_iterator(&ContainerPointers::begin, &ContainerPointers::end);
200
+
201
+ ContainerPointers* container = new ContainerPointers();
202
+ Object wrapper = Data_Object<ContainerPointers>(container);
203
+
204
+ Module m = define_module("TestingModule");
205
+
206
+ std::string code = R"(result = []
207
+ container = ContainerPointers.new
208
+ container.each do |x|
209
+ result << x
210
+ end
211
+ result)";
212
+
213
+ Array a = m.module_eval(code);
214
+
215
+ Data_Object<Data> wrappedData(a[0]);
216
+ ASSERT_EQUAL(1, wrappedData->index);
217
+
218
+ wrappedData = (Data_Object<Data>)a[1];
219
+ ASSERT_EQUAL(2, wrappedData->index);
220
+
221
+ wrappedData = (Data_Object<Data>)a[2];
222
+ ASSERT_EQUAL(3, wrappedData->index);
223
+ }
224
+
225
+ TESTCASE(two_iterator_pointer)
226
+ {
227
+ define_class<Data>("Data")
228
+ .define_constructor(Constructor<Data, uint32_t>());
229
+
230
+ define_class<ContainerPointers>("ContainerPointers")
231
+ .define_constructor(Constructor<ContainerPointers>())
232
+ .define_iterator(&ContainerPointers::begin, &ContainerPointers::end)
233
+ .define_iterator(&ContainerPointers::rbegin, &ContainerPointers::rend, "reach");
234
+
235
+ ContainerPointers* container = new ContainerPointers();
236
+ Object wrapper = Data_Object<ContainerPointers>(container);
237
+
238
+ Module m = define_module("TestingModule");
239
+
240
+ std::string code = R"(result = []
241
+ container = ContainerPointers.new
242
+ container.each do |x|
243
+ result << x
244
+ end
245
+ container.reach do |x|
246
+ result << x
247
+ end
248
+ result)";
249
+
250
+ Array a = m.module_eval(code);
251
+
252
+ ASSERT_EQUAL(6u, a.size());
253
+
254
+ Data_Object<Data> wrappedData(a[0]);
255
+ ASSERT_EQUAL(1, wrappedData->index);
256
+
257
+ wrappedData = (Data_Object<Data>)a[1];
258
+ ASSERT_EQUAL(2, wrappedData->index);
259
+
260
+ wrappedData = (Data_Object<Data>)a[2];
261
+ ASSERT_EQUAL(3, wrappedData->index);
262
+
263
+ wrappedData = (Data_Object<Data>)a[3];
264
+ ASSERT_EQUAL(3, wrappedData->index);
265
+
266
+ wrappedData = (Data_Object<Data>)a[4];
267
+ ASSERT_EQUAL(2, wrappedData->index);
268
+
269
+ wrappedData = (Data_Object<Data>)a[5];
270
+ ASSERT_EQUAL(1, wrappedData->index);
271
+ }
272
+
273
+ TESTCASE(map)
274
+ {
275
+ define_class<Data>("Data")
276
+ .define_constructor(Constructor<Data, uint32_t>())
277
+ .define_attr("index", &Data::index, Rice::AttrAccess::Read);
278
+
279
+ define_class<ContainerPointers>("ContainerPointers")
280
+ .define_constructor(Constructor<ContainerPointers>())
281
+ .define_iterator(&ContainerPointers::begin, &ContainerPointers::end);
282
+
283
+ Module m = define_module("Testing");
284
+
285
+ std::string code = R"(container = ContainerPointers.new
286
+ container.map do |data|
287
+ data.index * 2
288
+ end)";
289
+
290
+ Array a = m.module_eval(code);
291
+ ASSERT_EQUAL(3u, a.size());
292
+
293
+ Object element = a[0];
294
+ ASSERT_EQUAL(2, detail::From_Ruby<int>().convert(element));
295
+
296
+ element = a[1];
297
+ ASSERT_EQUAL(4, detail::From_Ruby<int>().convert(element));
298
+
299
+ element = a[2];
300
+ ASSERT_EQUAL(6, detail::From_Ruby<int>().convert(element));
301
+ }
302
+
303
+ TESTCASE(to_enum)
304
+ {
305
+ define_class<Data>("Data")
306
+ .define_constructor(Constructor<Data, uint32_t>());
307
+
308
+ define_class<ContainerPointers>("ContainerPointers")
309
+ .define_constructor(Constructor<ContainerPointers>())
310
+ .define_iterator(&ContainerPointers::begin, &ContainerPointers::end);
311
+
312
+ Module m = define_module("TestingModule");
313
+
314
+ std::string code = R"(container = ContainerPointers.new
315
+ container.each.map do |data|
316
+ data.index * 2
317
+ end)";
318
+
319
+ Array a = m.module_eval(code);
320
+
321
+ ASSERT_EQUAL(3u, a.size());
322
+
323
+ Object element = a[0];
324
+ ASSERT_EQUAL(2, detail::From_Ruby<int>().convert(element));
325
+
326
+ element = a[1];
327
+ ASSERT_EQUAL(4, detail::From_Ruby<int>().convert(element));
328
+
329
+ element = a[2];
330
+ ASSERT_EQUAL(6, detail::From_Ruby<int>().convert(element));
331
+ }
332
+
333
+ TESTCASE(IterateNoCopy)
334
+ {
335
+ define_class<Data>("Data")
336
+ .define_constructor(Constructor<Data, uint32_t>());
337
+
338
+ define_class<ContainerPointers>("ContainerValues")
339
+ .define_constructor(Constructor<ContainerValues>())
340
+ .define_iterator(&ContainerPointers::begin, &ContainerPointers::end);
341
+
342
+ Module m = define_module("Testing");
343
+
344
+ ContainerValues container;
345
+ Data_Object<ContainerValues> wrapper(container);
346
+ Array a = wrapper.instance_eval("self.to_a");
347
+
348
+ ASSERT_EQUAL(container.data_.size(), a.size());
349
+
350
+ for (int i = 0; i < container.data_.size(); i++)
351
+ {
352
+ Data& expected = container.data_[i];
353
+ Data_Object<Data> actual(a[i]);
354
+ ASSERT_EQUAL(&expected, &(*actual));
355
+ }
356
+ }