rice 4.0.1 → 4.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/include/rice/stl.hpp +1113 -0
  3. data/lib/version.rb +1 -1
  4. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4907c1eb3ab9b46fdda3cd3b53af5060130fed6a450faec8a5c1f0ea621b3bfd
4
- data.tar.gz: f05c603474db6cf63fd64c6fd8272801fe22a3ce3d4820abb1d06d1078d39db5
3
+ metadata.gz: fd2dbd87d7e696f34f2ab356874da9111c29b07978e995610a8beedb748ed2b2
4
+ data.tar.gz: 520234302f9c41a4f1f05e0ea9a2f0248d027e2b50cd23ad6be4c385a50e298d
5
5
  SHA512:
6
- metadata.gz: 9935fa0a5d12cdb06bd53742c2668e3219a18ff6acbd2103b731b3b69ae614b628034860ecab4ac49caf37e7e2842b241b9a7628f725cac3a2cfae0bf5724b2d
7
- data.tar.gz: 5a8b016fe5e539348eb7c5d4c3d74b8d2f638d13a913d1f334a6cf81d46eb410428ca59294650b0ac4407c1ad654d3237f1402bbe3ff7230c5ea6f014e7266a1
6
+ metadata.gz: 4143949294a979297f879f6e2392f8ef20a04a0c03e33ed177de7f43d6b81adb0807af4467665a83428dbc668104bd352492834edc658684a5a7eb93f3b6bdef
7
+ data.tar.gz: 35bb595dc8ec7d34ea290739606ab0176fae71f8b80d038e09655b10acab7f30daafd200d7af224569fd8d2b22709bc8658ddf3d1f30175231f0cfbd29cbc5a7
@@ -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_
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rice
2
- VERSION = "4.0.1"
2
+ VERSION = "4.0.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rice
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.1
4
+ version: 4.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Brannan
@@ -74,6 +74,7 @@ files:
74
74
  - README.md
75
75
  - Rakefile
76
76
  - include/rice/rice.hpp
77
+ - include/rice/stl.hpp
77
78
  - lib/mkmf-rice.rb
78
79
  - lib/version.rb
79
80
  - rice/Address_Registration_Guard.hpp
@@ -212,7 +213,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
212
213
  requirements:
213
214
  - - ">="
214
215
  - !ruby/object:Gem::Version
215
- version: '2.5'
216
+ version: '2.6'
216
217
  required_rubygems_version: !ruby/object:Gem::Requirement
217
218
  requirements:
218
219
  - - ">="