rice 4.8.0 → 4.9.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,19 +1,25 @@
1
1
  #ifndef Rice__stl__unique_ptr__hpp_
2
2
  #define Rice__stl__unique_ptr__hpp_
3
3
 
4
+ namespace Rice
5
+ {
6
+ template<typename T>
7
+ Data_Type<std::unique_ptr<T>> define_unique_ptr(std::string klassName = "");
8
+ }
9
+
4
10
  namespace Rice::detail
5
11
  {
6
12
  template<typename T>
7
13
  class Wrapper<std::unique_ptr<T>> : public WrapperBase
8
14
  {
9
15
  public:
10
- Wrapper(std::unique_ptr<T>&& data);
16
+ Wrapper(rb_data_type_t* rb_data_type, std::unique_ptr<T>&& data);
11
17
  ~Wrapper();
12
- void* get() override;
13
- std::unique_ptr<T>& data();
18
+ void* get(rb_data_type_t* requestedType) override;
14
19
 
15
20
  private:
16
21
  std::unique_ptr<T> data_;
22
+ rb_data_type_t* inner_rb_data_type_;
17
23
  };
18
24
  }
19
25
 
@@ -1,135 +1,123 @@
1
1
  #include <memory>
2
2
 
3
- namespace Rice::detail
3
+ namespace Rice
4
4
  {
5
5
  template<typename T>
6
- inline Wrapper<std::unique_ptr<T>>::Wrapper(std::unique_ptr<T>&& data)
7
- : data_(std::move(data))
8
- {
9
- }
10
-
11
- template<typename T>
12
- inline Wrapper<std::unique_ptr<T>>::~Wrapper()
13
- {
14
- Registries::instance.instances.remove(this->get());
15
- }
16
-
17
- template<typename T>
18
- inline void* Wrapper<std::unique_ptr<T>>::get()
19
- {
20
- return (void*)this->data_.get();
21
- }
22
-
23
- template<typename T>
24
- inline std::unique_ptr<T>& Wrapper<std::unique_ptr<T>>::data()
6
+ Data_Type<std::unique_ptr<T>> define_unique_ptr(std::string klassName)
25
7
  {
26
- return data_;
27
- }
8
+ using UniquePtr_T = std::unique_ptr<T>;
9
+ using Data_Type_T = Data_Type<UniquePtr_T>;
28
10
 
29
- template <typename T>
30
- class To_Ruby<std::unique_ptr<T>>
31
- {
32
- public:
33
- To_Ruby() = default;
34
-
35
- explicit To_Ruby(Arg* arg) : arg_(arg)
11
+ if (klassName.empty())
36
12
  {
13
+ detail::TypeMapper<UniquePtr_T> typeMapper;
14
+ klassName = typeMapper.rubyName();
37
15
  }
38
16
 
39
- VALUE convert(std::unique_ptr<T>& data)
17
+ Module rb_mStd = define_module("Std");
18
+ if (Data_Type_T::check_defined(klassName, rb_mStd))
40
19
  {
41
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(*data);
42
- return detail::wrap<std::unique_ptr<T>>(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
20
+ return Data_Type_T();
43
21
  }
44
22
 
45
- VALUE convert(std::unique_ptr<T>&& data)
23
+ Identifier id(klassName);
24
+ Data_Type_T result = define_class_under<detail::intrinsic_type<UniquePtr_T>>(rb_mStd, id).
25
+ define_method("get", &UniquePtr_T::get).
26
+ define_method("release", &UniquePtr_T::release).
27
+ define_method("reset", &UniquePtr_T::reset).
28
+ define_method("swap", &UniquePtr_T::swap).
29
+ define_method("empty?", [](UniquePtr_T& self)->bool
30
+ {
31
+ return !self;
32
+ });
33
+
34
+ // Setup delegation to forward T's methods via get (only for non-fundamental, non-void types)
35
+ if constexpr (!std::is_void_v<T> && !std::is_fundamental_v<T>)
46
36
  {
47
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(*data);
48
- return detail::wrap<std::unique_ptr<T>>(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
37
+ detail::define_forwarding(result.klass(), Data_Type<T>::klass());
49
38
  }
50
39
 
51
- private:
52
- Arg* arg_ = nullptr;
53
- };
40
+ return result;
41
+ }
42
+ }
54
43
 
55
- template <typename T>
56
- class To_Ruby<std::unique_ptr<T>&>
44
+ // --------- Wrapper ---------
45
+ namespace Rice::detail
46
+ {
47
+ template<typename T>
48
+ Wrapper<std::unique_ptr<T>>::Wrapper(rb_data_type_t* rb_data_type, std::unique_ptr<T>&& data)
49
+ : WrapperBase(rb_data_type), data_(std::move(data))
57
50
  {
58
- public:
59
- To_Ruby() = default;
51
+ using Intrinsic_T = intrinsic_type<T>;
60
52
 
61
- explicit To_Ruby(Arg* arg) : arg_(arg)
53
+ if constexpr (std::is_fundamental_v<Intrinsic_T>)
62
54
  {
55
+ inner_rb_data_type_ = Data_Type<Pointer<Intrinsic_T>>::ruby_data_type();
63
56
  }
64
-
65
- VALUE convert(std::unique_ptr<T>& data)
57
+ else
66
58
  {
67
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(*data);
68
- return detail::wrap<std::unique_ptr<T>>(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
59
+ inner_rb_data_type_ = Data_Type<Intrinsic_T>::ruby_data_type();
69
60
  }
61
+ }
70
62
 
71
- private:
72
- Arg* arg_ = nullptr;
73
- };
63
+ template<typename T>
64
+ Wrapper<std::unique_ptr<T>>::~Wrapper()
65
+ {
66
+ Registries::instance.instances.remove(this->get(this->rb_data_type_));
67
+ }
74
68
 
75
- template <typename T>
76
- class From_Ruby<std::unique_ptr<T>>
69
+ template<typename T>
70
+ void* Wrapper<std::unique_ptr<T>>::get(rb_data_type_t* requestedType)
77
71
  {
78
- public:
79
- Wrapper<std::unique_ptr<T>>* is_same_smart_ptr(VALUE value)
72
+ if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
80
73
  {
81
- WrapperBase* wrapper = detail::getWrapper(value, Data_Type<T>::ruby_data_type());
82
- return dynamic_cast<Wrapper<std::unique_ptr<T>>*>(wrapper);
74
+ return &this->data_;
83
75
  }
84
-
85
- From_Ruby() = default;
86
-
87
- explicit From_Ruby(Arg* arg) : arg_(arg)
76
+ else if (rb_typeddata_inherited_p(this->inner_rb_data_type_, requestedType))
77
+ {
78
+ return this->data_.get();
79
+ }
80
+ else
88
81
  {
82
+ throw Exception(rb_eTypeError, "wrong argument type (expected %s)",
83
+ requestedType->wrap_struct_name);
89
84
  }
85
+ }
90
86
 
91
- double is_convertible(VALUE value)
87
+ }
88
+
89
+ // --------- Type ---------
90
+ namespace Rice::detail
91
+ {
92
+ template<typename T>
93
+ struct Type<std::unique_ptr<T>>
94
+ {
95
+ static bool verify()
92
96
  {
93
- if (!is_same_smart_ptr(value))
97
+ bool result = true;
98
+ if constexpr (std::is_fundamental_v<T>)
94
99
  {
95
- return Convertible::None;
100
+ result = result && Type<Pointer<T>>::verify();
96
101
  }
97
-
98
- switch (rb_type(value))
102
+ else
99
103
  {
100
- case RUBY_T_DATA:
101
- return Convertible::Exact;
102
- break;
103
- default:
104
- return Convertible::None;
104
+ result = result && Type<T>::verify();
105
105
  }
106
- }
107
106
 
108
- std::unique_ptr<T> convert(VALUE value)
109
- {
110
- Wrapper<std::unique_ptr<T>>* wrapper = is_same_smart_ptr(value);
111
- if (!wrapper)
107
+ if (result)
112
108
  {
113
- std::string message = "Invalid smart pointer wrapper";
114
- throw std::runtime_error(message.c_str());
109
+ define_unique_ptr<T>();
115
110
  }
116
- return std::move(wrapper->data());
117
- }
118
111
 
119
- private:
120
- Arg* arg_ = nullptr;
112
+ return result;
113
+ }
121
114
  };
122
115
 
116
+ // --------- From_Ruby ---------
123
117
  template <typename T>
124
- class From_Ruby<std::unique_ptr<T>&>
118
+ class From_Ruby<std::unique_ptr<T>>
125
119
  {
126
120
  public:
127
- Wrapper<std::unique_ptr<T>>* is_same_smart_ptr(VALUE value)
128
- {
129
- WrapperBase* wrapper = detail::getWrapper(value, Data_Type<T>::ruby_data_type());
130
- return dynamic_cast<Wrapper<std::unique_ptr<T>>*>(wrapper);
131
- }
132
-
133
121
  From_Ruby() = default;
134
122
 
135
123
  explicit From_Ruby(Arg* arg) : arg_(arg)
@@ -138,11 +126,6 @@ namespace Rice::detail
138
126
 
139
127
  double is_convertible(VALUE value)
140
128
  {
141
- if (!is_same_smart_ptr(value))
142
- {
143
- return Convertible::None;
144
- }
145
-
146
129
  switch (rb_type(value))
147
130
  {
148
131
  case RUBY_T_DATA:
@@ -153,41 +136,14 @@ namespace Rice::detail
153
136
  }
154
137
  }
155
138
 
156
- std::unique_ptr<T>& convert(VALUE value)
139
+ std::unique_ptr<T> convert(VALUE value)
157
140
  {
158
- Wrapper<std::unique_ptr<T>>* wrapper = is_same_smart_ptr(value);
159
- if (!wrapper)
160
- {
161
- std::string message = "Invalid smart pointer wrapper";
162
- throw std::runtime_error(message.c_str());
163
- }
164
- return wrapper->data();
141
+ std::unique_ptr<T>* result = detail::unwrap<std::unique_ptr<T>>(value, Data_Type<std::unique_ptr<T>>::ruby_data_type(), this->arg_ && this->arg_->isOwner());
142
+ // The reason we need this overriden From_Ruby is to do this std::move.
143
+ return std::move(*result);
165
144
  }
166
145
 
167
146
  private:
168
147
  Arg* arg_ = nullptr;
169
148
  };
170
-
171
- template<typename T>
172
- struct Type<std::unique_ptr<T>>
173
- {
174
- static bool verify()
175
- {
176
- if constexpr (std::is_fundamental_v<T>)
177
- {
178
- return Type<Pointer<T>>::verify();
179
- return Type<Buffer<T>>::verify();
180
- }
181
- else
182
- {
183
- return Type<T>::verify();
184
- }
185
- }
186
-
187
- static VALUE rubyKlass()
188
- {
189
- TypeMapper<T> typeMapper;
190
- return typeMapper.rubyKlass();
191
- }
192
- };
193
149
  }
@@ -128,12 +128,12 @@ TESTCASE(base_pointer_method_call)
128
128
 
129
129
  Module m = define_module("Testing");
130
130
 
131
- Object message = m.module_eval(R"EOS(notification = EmailNotification.new
132
- notification.message)EOS");
131
+ Object message = m.module_eval(R"(notification = EmailNotification.new
132
+ notification.message)");
133
133
  ASSERT_EQUAL("Email", detail::From_Ruby<std::string>().convert(message));
134
134
 
135
- message = m.module_eval(R"EOS(notification = PushNotification.new
136
- notification.message)EOS");
135
+ message = m.module_eval(R"(notification = PushNotification.new
136
+ notification.message)");
137
137
  ASSERT_EQUAL("Push", detail::From_Ruby<std::string>().convert(message));
138
138
  }
139
139
 
@@ -151,12 +151,12 @@ TESTCASE(base_pointer_function_argument)
151
151
  define_global_function("process_notification", &processNotification);
152
152
 
153
153
  Module m = define_module("Testing");
154
- Object message = m.module_eval(R"EOS(notification = EmailNotification.new
155
- process_notification(notification))EOS");
154
+ Object message = m.module_eval(R"(notification = EmailNotification.new
155
+ process_notification(notification))");
156
156
  ASSERT_EQUAL("Email", detail::From_Ruby<std::string>().convert(message));
157
157
 
158
- message = m.module_eval(R"EOS(notification = PushNotification.new
159
- process_notification(notification))EOS");
158
+ message = m.module_eval(R"(notification = PushNotification.new
159
+ process_notification(notification))");
160
160
  ASSERT_EQUAL("Push", detail::From_Ruby<std::string>().convert(message));
161
161
  }
162
162
 
@@ -175,12 +175,12 @@ TESTCASE(module_base_pointer_method_call)
175
175
 
176
176
  Module m = define_module("Testing");
177
177
 
178
- Object message = m.module_eval(R"EOS(notification = Inheritance::EmailNotification.new
179
- notification.message)EOS");
178
+ Object message = m.module_eval(R"(notification = Inheritance::EmailNotification.new
179
+ notification.message)");
180
180
  ASSERT_EQUAL("Email", detail::From_Ruby<std::string>().convert(message));
181
181
 
182
- message = m.module_eval(R"EOS(notification = Inheritance::PushNotification.new
183
- notification.message)EOS");
182
+ message = m.module_eval(R"(notification = Inheritance::PushNotification.new
183
+ notification.message)");
184
184
  ASSERT_EQUAL("Push", detail::From_Ruby<std::string>().convert(message));
185
185
  }
186
186
 
@@ -219,8 +219,8 @@ TESTCASE(base_pointer_constructor)
219
219
 
220
220
  Module m = define_module("Testing");
221
221
 
222
- Object result = m.module_eval(R"EOS(notification = PushNotification.new
222
+ Object result = m.module_eval(R"(notification = PushNotification.new
223
223
  processor = Processor.new(notification)
224
- processor.process)EOS");
224
+ processor.process)");
225
225
  ASSERT_EQUAL("Push", detail::From_Ruby<std::string>().convert(result));
226
226
  }
@@ -75,11 +75,15 @@ TESTCASE(test_keep_alive_no_wrapper)
75
75
  Module m = define_module("TestingModule");
76
76
  Object zoo = m.module_eval("@zoo = Zoo.new");
77
77
 
78
+ std::string code = R"(@zoo.get_pets.each do |pet|
79
+ puts pet.get_name
80
+ end)";
81
+
78
82
  // get_pets returns an Array (builtin type) so Return().keepAlive()
79
- // shall result in std::runtime_error
83
+ // should result in std::runtime_error
80
84
  ASSERT_EXCEPTION_CHECK(
81
85
  Exception,
82
- m.module_eval("@zoo.get_pets.each do |pet| puts pet.name; end"),
86
+ m.module_eval(code),
83
87
  ASSERT_EQUAL("wrong argument type Array (expected wrapped C++ object)",
84
88
  ex.what())
85
89
  );