rice 4.6.1 → 4.7.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 (185) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/CMakeLists.txt +0 -4
  4. data/Rakefile +2 -8
  5. data/bin/rice-doc.rb +212 -0
  6. data/bin/rice-rbs.rb +93 -0
  7. data/include/rice/rice.hpp +4972 -4015
  8. data/include/rice/stl.hpp +822 -294
  9. data/lib/rice/doc/cpp_reference.rb +166 -0
  10. data/lib/rice/doc/doxygen.rb +294 -0
  11. data/lib/rice/doc/mkdocs.rb +298 -0
  12. data/lib/rice/doc/rice.rb +29 -0
  13. data/lib/rice/doc/ruby.rb +37 -0
  14. data/lib/rice/doc.rb +5 -0
  15. data/lib/{make_rice_headers.rb → rice/make_rice_headers.rb} +3 -0
  16. data/lib/rice/native.rb +18 -0
  17. data/lib/rice/native_registry.rb +21 -0
  18. data/lib/rice/parameter.rb +7 -0
  19. data/lib/rice/rbs.rb +104 -0
  20. data/lib/rice/version.rb +1 -1
  21. data/lib/rice.rb +4 -0
  22. data/lib/rubygems/cmake_builder.rb +24 -27
  23. data/rice/Arg.hpp +4 -4
  24. data/rice/Arg.ipp +4 -4
  25. data/rice/Buffer.hpp +32 -28
  26. data/rice/Buffer.ipp +306 -178
  27. data/rice/Data_Object.ipp +101 -82
  28. data/rice/Data_Type.hpp +5 -7
  29. data/rice/Data_Type.ipp +48 -29
  30. data/rice/Enum.ipp +15 -21
  31. data/rice/Function.hpp +17 -0
  32. data/rice/Function.ipp +13 -0
  33. data/rice/Pointer.hpp +15 -0
  34. data/rice/Pointer.ipp +49 -0
  35. data/rice/Return.hpp +1 -1
  36. data/rice/Return.ipp +2 -2
  37. data/rice/api.hpp +30 -0
  38. data/rice/cpp_api/Array.hpp +2 -2
  39. data/rice/cpp_api/Array.ipp +50 -5
  40. data/rice/cpp_api/Class.hpp +0 -5
  41. data/rice/cpp_api/Class.ipp +19 -0
  42. data/rice/cpp_api/Hash.ipp +20 -0
  43. data/rice/cpp_api/Module.hpp +6 -3
  44. data/rice/cpp_api/Module.ipp +49 -11
  45. data/rice/cpp_api/Object.ipp +31 -2
  46. data/rice/cpp_api/String.hpp +1 -2
  47. data/rice/cpp_api/String.ipp +21 -1
  48. data/rice/cpp_api/Struct.ipp +5 -0
  49. data/rice/cpp_api/Symbol.ipp +34 -0
  50. data/rice/cpp_api/shared_methods.hpp +12 -12
  51. data/rice/detail/MethodInfo.hpp +4 -2
  52. data/rice/detail/MethodInfo.ipp +19 -3
  53. data/rice/detail/ModuleRegistry.hpp +18 -0
  54. data/rice/detail/ModuleRegistry.ipp +25 -0
  55. data/rice/detail/Native.hpp +45 -2
  56. data/rice/detail/Native.ipp +196 -2
  57. data/rice/detail/NativeAttributeGet.hpp +9 -4
  58. data/rice/detail/NativeAttributeGet.ipp +65 -11
  59. data/rice/detail/NativeAttributeSet.hpp +4 -0
  60. data/rice/detail/NativeAttributeSet.ipp +30 -2
  61. data/rice/detail/NativeCallbackFFI.ipp +2 -2
  62. data/rice/detail/NativeCallbackSimple.ipp +1 -1
  63. data/rice/detail/NativeFunction.hpp +11 -49
  64. data/rice/detail/NativeFunction.ipp +82 -379
  65. data/rice/detail/NativeInvoker.hpp +74 -0
  66. data/rice/detail/NativeInvoker.ipp +197 -0
  67. data/rice/detail/NativeIterator.hpp +4 -0
  68. data/rice/detail/NativeIterator.ipp +19 -0
  69. data/rice/detail/NativeMethod.hpp +97 -0
  70. data/rice/detail/NativeMethod.ipp +332 -0
  71. data/rice/detail/NativeProc.hpp +51 -0
  72. data/rice/detail/NativeProc.ipp +133 -0
  73. data/rice/detail/NativeRegistry.hpp +8 -0
  74. data/rice/detail/NativeRegistry.ipp +27 -0
  75. data/rice/detail/Parameter.hpp +47 -0
  76. data/rice/detail/Parameter.ipp +105 -0
  77. data/rice/detail/Proc.ipp +14 -13
  78. data/rice/detail/Registries.hpp +1 -0
  79. data/rice/detail/RubyType.hpp +0 -2
  80. data/rice/detail/RubyType.ipp +15 -33
  81. data/rice/detail/Type.hpp +44 -8
  82. data/rice/detail/Type.ipp +151 -49
  83. data/rice/detail/TypeRegistry.hpp +3 -0
  84. data/rice/detail/TypeRegistry.ipp +17 -27
  85. data/rice/detail/Types.ipp +430 -0
  86. data/rice/detail/Wrapper.hpp +12 -0
  87. data/rice/detail/Wrapper.ipp +45 -2
  88. data/rice/detail/from_ruby.ipp +567 -1073
  89. data/rice/detail/ruby.hpp +1 -0
  90. data/rice/detail/to_ruby.ipp +4 -635
  91. data/rice/libc/file.ipp +3 -6
  92. data/rice/rice.hpp +22 -12
  93. data/rice/rice_api/Arg.hpp +7 -0
  94. data/rice/rice_api/Arg.ipp +9 -0
  95. data/rice/rice_api/ModuleRegistry.hpp +7 -0
  96. data/rice/rice_api/ModuleRegistry.ipp +10 -0
  97. data/rice/rice_api/Native.hpp +7 -0
  98. data/rice/rice_api/Native.ipp +52 -0
  99. data/rice/rice_api/NativeRegistry.hpp +7 -0
  100. data/rice/rice_api/NativeRegistry.ipp +21 -0
  101. data/rice/rice_api/Parameter.hpp +7 -0
  102. data/rice/rice_api/Parameter.ipp +11 -0
  103. data/rice/rice_api/Registries.hpp +6 -0
  104. data/rice/rice_api/Registries.ipp +12 -0
  105. data/rice/rice_api/TypeRegistry.hpp +7 -0
  106. data/rice/rice_api/TypeRegistry.ipp +10 -0
  107. data/rice/stl/complex.ipp +35 -0
  108. data/rice/stl/exception.ipp +20 -7
  109. data/rice/stl/filesystem.hpp +6 -0
  110. data/rice/stl/filesystem.ipp +34 -0
  111. data/rice/stl/map.ipp +13 -21
  112. data/rice/stl/monostate.ipp +37 -1
  113. data/rice/stl/multimap.ipp +17 -24
  114. data/rice/stl/optional.ipp +47 -2
  115. data/rice/stl/pair.ipp +23 -58
  116. data/rice/stl/reference_wrapper.ipp +22 -1
  117. data/rice/stl/set.ipp +17 -9
  118. data/rice/stl/shared_ptr.ipp +44 -17
  119. data/rice/stl/string.ipp +175 -7
  120. data/rice/stl/string_view.ipp +5 -0
  121. data/rice/stl/tuple.ipp +38 -9
  122. data/rice/stl/unique_ptr.ipp +46 -2
  123. data/rice/stl/unordered_map.ipp +13 -21
  124. data/rice/stl/variant.ipp +47 -11
  125. data/rice/stl/vector.ipp +183 -104
  126. data/rice/stl.hpp +1 -0
  127. data/rice/traits/function_traits.hpp +2 -2
  128. data/rice/traits/method_traits.hpp +5 -16
  129. data/rice/traits/rice_traits.hpp +24 -4
  130. data/rice.gemspec +11 -22
  131. data/test/embed_ruby.cpp +0 -3
  132. data/test/test_Array.cpp +38 -38
  133. data/test/test_Attribute.cpp +187 -2
  134. data/test/test_Buffer.cpp +302 -26
  135. data/test/test_Callback.cpp +2 -3
  136. data/test/test_Class.cpp +5 -5
  137. data/test/test_Data_Object.cpp +0 -55
  138. data/test/test_Data_Type.cpp +19 -30
  139. data/test/test_Enum.cpp +4 -46
  140. data/test/test_From_Ruby.cpp +88 -81
  141. data/test/test_GVL.cpp +109 -0
  142. data/test/test_Iterator.cpp +1 -1
  143. data/test/test_Keep_Alive_No_Wrapper.cpp +5 -3
  144. data/test/test_Module.cpp +8 -9
  145. data/test/test_Object.cpp +1 -1
  146. data/test/test_Overloads.cpp +3 -3
  147. data/test/test_Stl_Map.cpp +8 -8
  148. data/test/test_Stl_Multimap.cpp +4 -4
  149. data/test/test_Stl_Pair.cpp +5 -3
  150. data/test/test_Stl_SharedPtr.cpp +24 -12
  151. data/test/test_Stl_Tuple.cpp +1 -1
  152. data/test/test_Stl_UniquePtr.cpp +8 -0
  153. data/test/test_Stl_Unordered_Map.cpp +9 -9
  154. data/test/test_Stl_Variant.cpp +9 -3
  155. data/test/test_Stl_Vector.cpp +118 -13
  156. data/test/test_To_Ruby.cpp +35 -28
  157. data/test/test_Type.cpp +256 -53
  158. data/test/unittest.hpp +35 -0
  159. metadata +66 -34
  160. data/rice/Init.hpp +0 -8
  161. data/rice/Init.ipp +0 -8
  162. data/rice/detail/RubyFunction.hpp +0 -31
  163. data/rice/detail/RubyFunction.ipp +0 -77
  164. data/sample/callbacks/extconf.rb +0 -5
  165. data/sample/callbacks/sample_callbacks.cpp +0 -35
  166. data/sample/callbacks/test.rb +0 -28
  167. data/sample/enum/extconf.rb +0 -5
  168. data/sample/enum/sample_enum.cpp +0 -40
  169. data/sample/enum/test.rb +0 -8
  170. data/sample/inheritance/animals.cpp +0 -82
  171. data/sample/inheritance/extconf.rb +0 -5
  172. data/sample/inheritance/test.rb +0 -7
  173. data/sample/map/extconf.rb +0 -5
  174. data/sample/map/map.cpp +0 -73
  175. data/sample/map/test.rb +0 -7
  176. data/test/ext/t1/Foo.hpp +0 -10
  177. data/test/ext/t1/extconf.rb +0 -4
  178. data/test/ext/t1/t1.cpp +0 -13
  179. data/test/ext/t2/extconf.rb +0 -4
  180. data/test/ext/t2/t2.cpp +0 -11
  181. data/test/ruby/test_callbacks_sample.rb +0 -28
  182. data/test/ruby/test_multiple_extensions.rb +0 -18
  183. data/test/ruby/test_multiple_extensions_same_class.rb +0 -14
  184. data/test/ruby/test_multiple_extensions_with_inheritance.rb +0 -20
  185. /data/test/{test_Stl_Type.cpp → test_Stl_Type_Info.cpp} +0 -0
data/rice/Buffer.ipp CHANGED
@@ -2,30 +2,35 @@ namespace Rice
2
2
  {
3
3
  // ---- Buffer<T> -------
4
4
  template<typename T>
5
- inline Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::Buffer(T* pointer) : m_buffer(pointer)
5
+ inline Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::Buffer(T* pointer) : m_buffer(pointer)
6
6
  {
7
7
  }
8
8
 
9
9
  template<typename T>
10
- inline Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::Buffer(T* pointer, size_t size) : m_size(size), m_buffer(pointer)
10
+ inline Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::Buffer(T* pointer, size_t size) : m_size(size), m_buffer(pointer)
11
11
  {
12
12
  }
13
13
 
14
14
  template <typename T>
15
- inline Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::Buffer(VALUE value)
15
+ inline Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::Buffer(VALUE value) : Buffer(value, 0)
16
+ {
17
+ }
18
+
19
+ template <typename T>
20
+ inline Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::Buffer(VALUE value, size_t size)
16
21
  {
17
22
  if constexpr (std::is_fundamental_v<T>)
18
23
  {
19
- this->fromBuiltinType(value);
24
+ this->fromBuiltinType(value, size);
20
25
  }
21
26
  else
22
27
  {
23
- this->fromWrappedType(value);
28
+ this->fromWrappedType(value, size);
24
29
  }
25
30
  }
26
31
 
27
32
  template <typename T>
28
- inline Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::~Buffer()
33
+ inline Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::~Buffer()
29
34
  {
30
35
  if constexpr (std::is_destructible_v<T>)
31
36
  {
@@ -37,12 +42,12 @@ namespace Rice
37
42
  }
38
43
 
39
44
  template <typename T>
40
- inline void Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::fromBuiltinType(VALUE value)
45
+ inline void Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::fromBuiltinType(VALUE value, size_t size)
41
46
  {
42
47
  using Intrinsic_T = typename detail::intrinsic_type<T>;
43
48
  using RubyType_T = typename detail::RubyType<Intrinsic_T>;
44
- ruby_value_type valueType = rb_type(value);
45
49
 
50
+ ruby_value_type valueType = rb_type(value);
46
51
  switch (valueType)
47
52
  {
48
53
  case RUBY_T_ARRAY:
@@ -51,9 +56,19 @@ namespace Rice
51
56
  this->m_size = array.size();
52
57
  this->m_buffer = new T[this->m_size]();
53
58
 
54
- String packed = array.pack<Intrinsic_T>();
55
- memcpy(this->m_buffer, RSTRING_PTR(packed.value()), RSTRING_LEN(packed.value()));
56
-
59
+ if constexpr (std::is_fundamental_v<T>)
60
+ {
61
+ String packed = array.pack<Intrinsic_T>();
62
+ memcpy((void*)this->m_buffer, RSTRING_PTR(packed.value()), RSTRING_LEN(packed.value()));
63
+ }
64
+ else
65
+ {
66
+ detail::From_Ruby<Intrinsic_T> fromRuby;
67
+ for (int i = 0; i < array.size(); i++)
68
+ {
69
+ this->m_buffer[0] = fromRuby.convert(array[i]);
70
+ }
71
+ }
57
72
  this->m_owner = true;
58
73
  break;
59
74
  }
@@ -69,21 +84,21 @@ namespace Rice
69
84
  {
70
85
  this->m_buffer = new T[this->m_size]();
71
86
  }
72
- memcpy(this->m_buffer, RSTRING_PTR(value), this->m_size);
87
+ memcpy((void*)this->m_buffer, RSTRING_PTR(value), this->m_size);
73
88
 
74
89
  this->m_owner = true;
75
90
  break;
76
91
  }
77
92
  case RUBY_T_DATA:
78
93
  {
79
- if (Data_Type<T>::is_descendant(value))
94
+ if (Data_Type<Pointer<T>>::is_descendant(value))
80
95
  {
81
- this->m_size = 1;
82
- this->m_buffer = new T[this->m_size]();
83
- this->m_buffer[0] = *detail::unwrap<T>(value, Data_Type<T>::ruby_data_type(), false);
96
+ this->m_buffer = detail::unwrap<T>(value, Data_Type<Pointer<T>>::ruby_data_type(), false);
84
97
  this->m_owner = false;
98
+ this->m_size = size;
85
99
  break;
86
100
  }
101
+ [[fallthrough]];
87
102
  }
88
103
  default:
89
104
  {
@@ -94,13 +109,14 @@ namespace Rice
94
109
  T data = detail::protect(RubyType_T::fromRuby, value);
95
110
  this->m_size = 1;
96
111
  this->m_buffer = new T[this->m_size]();
97
- memcpy(this->m_buffer, &data, sizeof(T));
112
+ memcpy((void*)this->m_buffer, &data, sizeof(T));
98
113
  this->m_owner = true;
99
114
  break;
100
115
  }
101
116
  else
102
117
  {
103
- std::string typeName = detail::typeName(typeid(T));
118
+ detail::TypeMapper<T> typeMapper;
119
+ std::string typeName = typeMapper.name();
104
120
  throw Exception(rb_eTypeError, "wrong argument type %s (expected % s*)",
105
121
  detail::protect(rb_obj_classname, value), typeName.c_str());
106
122
  }
@@ -109,7 +125,7 @@ namespace Rice
109
125
  }
110
126
 
111
127
  template <typename T>
112
- inline void Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::fromWrappedType(VALUE value)
128
+ inline void Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::fromWrappedType(VALUE value, size_t size)
113
129
  {
114
130
  using Intrinsic_T = typename detail::intrinsic_type<T>;
115
131
 
@@ -120,20 +136,68 @@ namespace Rice
120
136
  Array array(value);
121
137
  this->m_size = array.size();
122
138
 
123
- // Use operator new[] to allocate memory but not call constructors
124
- this->m_buffer = static_cast<T*>(operator new[](sizeof(T)* this->m_size));
139
+ // Use operator new[] to allocate memory but not call constructors.
140
+ size_t size = sizeof(T) * this->m_size;
141
+ this->m_buffer = static_cast<T*>(operator new[](size));
125
142
 
126
143
  detail::From_Ruby<Intrinsic_T> fromRuby;
127
144
 
128
145
  for (size_t i = 0; i < this->m_size; i++)
129
146
  {
130
- this->m_buffer[i] = fromRuby.convert(array[i].value());
147
+ // Construct objects in allocated memory using move or copy construction
148
+ if constexpr (std::is_move_constructible_v<T>)
149
+ {
150
+ new (&this->m_buffer[i]) T(std::move(fromRuby.convert(array[i].value())));
151
+ }
152
+ else if constexpr (std::is_copy_constructible_v<T>)
153
+ {
154
+ new (&this->m_buffer[i]) T(fromRuby.convert(array[i].value()));
155
+ }
156
+ else
157
+ {
158
+ throw Exception(rb_eTypeError, "Cannot construct object of type %s - type is not move or copy constructible",
159
+ detail::TypeMapper<Intrinsic_T>().name().c_str());
160
+ }
131
161
  }
132
162
  break;
133
163
  }
164
+ case RUBY_T_DATA:
165
+ {
166
+ if (Data_Type<Pointer<Intrinsic_T>>::is_descendant(value))
167
+ {
168
+ this->m_buffer = detail::unwrap<T>(value, Data_Type<Pointer<Intrinsic_T>>::ruby_data_type(), false);
169
+ this->m_owner = false;
170
+ this->m_size = size;
171
+ break;
172
+ }
173
+ else if (Data_Type<Intrinsic_T>::is_descendant(value))
174
+ {
175
+ this->m_buffer = detail::unwrap<T>(value, Data_Type<Intrinsic_T>::ruby_data_type(), false);
176
+ this->m_owner = false;
177
+ this->m_size = size;
178
+ break;
179
+ }
180
+ }
181
+ case RUBY_T_STRING:
182
+ {
183
+ // This special case is a bit ugly...
184
+ if constexpr (std::is_same_v<detail::intrinsic_type<T>, std::string>)
185
+ {
186
+ // FromRuby owns the converted string so we need to keep it alive until we get to the copy constructor
187
+ // two lines down
188
+ detail::From_Ruby<T*> fromRuby;
189
+ T* converted = fromRuby.convert(value);
190
+ this->m_buffer = new T[1]{ *converted };
191
+ this->m_owner = true;
192
+ this->m_size = 1;
193
+ break;
194
+ }
195
+ [[fallthrough]];
196
+ }
134
197
  default:
135
198
  {
136
- std::string typeName = detail::typeName(typeid(T));
199
+ detail::TypeMapper<T> typeMapper;
200
+ std::string typeName = typeMapper.name();
137
201
  throw Exception(rb_eTypeError, "wrong argument type %s (expected % s*)",
138
202
  detail::protect(rb_obj_classname, value), typeName.c_str());
139
203
  }
@@ -141,7 +205,7 @@ namespace Rice
141
205
  }
142
206
 
143
207
  template <typename T>
144
- inline Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::Buffer(Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>&& other) : m_owner(other.m_owner), m_size(other.m_size), m_buffer(other.m_buffer)
208
+ inline Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::Buffer(Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>&& other) : m_owner(other.m_owner), m_size(other.m_size), m_buffer(other.m_buffer)
145
209
  {
146
210
  other.m_buffer = nullptr;
147
211
  other.m_size = 0;
@@ -149,7 +213,7 @@ namespace Rice
149
213
  }
150
214
 
151
215
  template <typename T>
152
- inline Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>& Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::operator=(Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>&& other)
216
+ inline Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>& Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::operator=(Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>&& other)
153
217
  {
154
218
  this->m_buffer = other.m_buffer;
155
219
  other.m_buffer = nullptr;
@@ -164,59 +228,54 @@ namespace Rice
164
228
  }
165
229
 
166
230
  template <typename T>
167
- inline size_t Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::size() const
231
+ inline size_t Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::size() const
168
232
  {
169
233
  return this->m_size;
170
234
  }
171
235
 
172
236
  template <typename T>
173
- void Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::setSize(size_t value)
174
- {
175
- this->m_size = value;
176
- }
177
-
178
- template <typename T>
179
- inline T* Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::ptr()
237
+ inline T* Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::ptr()
180
238
  {
181
239
  return this->m_buffer;
182
240
  }
183
241
 
184
242
  template <typename T>
185
- inline T& Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::reference()
243
+ inline T& Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::reference()
186
244
  {
187
245
  return *this->m_buffer;
188
246
  }
189
247
 
190
248
  template <typename T>
191
- inline bool Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::isOwner() const
249
+ inline T* Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::release()
192
250
  {
193
- return this->m_owner;
251
+ this->m_owner = false;
252
+ return this->m_buffer;
194
253
  }
195
254
 
196
255
  template <typename T>
197
- inline void Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::setOwner(bool value)
256
+ inline bool Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::isOwner() const
198
257
  {
199
- this->m_owner = value;
258
+ return this->m_owner;
200
259
  }
201
260
 
202
261
  template <typename T>
203
- inline void Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::release()
262
+ inline void Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::setOwner(bool value)
204
263
  {
205
- this->m_owner = false;
264
+ this->m_owner = value;
206
265
  }
207
266
 
208
267
  template<typename T>
209
- inline VALUE Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::toString() const
268
+ inline VALUE Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::toString() const
210
269
  {
211
- std::string name = detail::typeName(typeid(T*));
212
- std::string description = "Buffer<type: " + detail::cppClassName(name) + ", size: " + std::to_string(this->m_size) + ">";
270
+ detail::TypeMapper<T*> typeMapper;
271
+ std::string description = "Buffer<type: " + typeMapper.simplifiedName() + ", size: " + std::to_string(this->m_size) + ">";
213
272
 
214
273
  // We can't use To_Ruby because To_Ruby depends on Buffer - ie a circular reference
215
274
  return detail::protect(rb_utf8_str_new_cstr, description.c_str());
216
275
  }
217
276
 
218
277
  template<typename T>
219
- inline VALUE Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::bytes(size_t count) const
278
+ inline VALUE Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::bytes(size_t count) const
220
279
  {
221
280
  if (!this->m_buffer)
222
281
  {
@@ -230,13 +289,13 @@ namespace Rice
230
289
  }
231
290
 
232
291
  template<typename T>
233
- inline VALUE Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::bytes() const
292
+ inline VALUE Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::bytes() const
234
293
  {
235
294
  return this->bytes(this->m_size);
236
295
  }
237
296
 
238
297
  template<typename T>
239
- inline Array Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::toArray(size_t count) const
298
+ inline Array Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::toArray(size_t count) const
240
299
  {
241
300
  if (!this->m_buffer)
242
301
  {
@@ -256,20 +315,20 @@ namespace Rice
256
315
 
257
316
  for (; ptr < end; ptr++)
258
317
  {
259
- result.push(*ptr);
318
+ result.push(*ptr, false);
260
319
  }
261
320
  return result;
262
321
  }
263
322
  }
264
323
 
265
324
  template<typename T>
266
- inline Array Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::toArray() const
325
+ inline Array Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::toArray() const
267
326
  {
268
327
  return this->toArray(this->m_size);
269
328
  }
270
329
 
271
330
  template<typename T>
272
- inline typename Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::Element_T& Buffer<T, std::enable_if_t<!std::is_pointer_v<T>>>::operator[](size_t index)
331
+ inline T& Buffer<T, std::enable_if_t<!std::is_pointer_v<T> && !std::is_void_v<T>>>::operator[](size_t index)
273
332
  {
274
333
  if (index >= this->m_size)
275
334
  {
@@ -281,49 +340,77 @@ namespace Rice
281
340
 
282
341
  // ---- Buffer<T*> - Builtin -------
283
342
  template<typename T>
284
- inline Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::Buffer(T** pointer) : m_outer(pointer)
343
+ inline Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::Buffer(T** pointer) : m_buffer(pointer)
285
344
  {
286
345
  }
287
346
 
288
347
  template<typename T>
289
- inline Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::Buffer(T** pointer, size_t size) : m_outer(pointer), m_size(size)
348
+ inline Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::Buffer(T** pointer, size_t size) : m_buffer(pointer), m_size(size)
290
349
  {
291
350
  }
292
351
 
293
352
  template <typename T>
294
- inline Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::Buffer(VALUE value)
353
+ inline Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::Buffer(VALUE value) : Buffer(value, 0)
295
354
  {
296
- ruby_value_type valueType = rb_type(value);
355
+ }
356
+
357
+ template <typename T>
358
+ inline Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::Buffer(VALUE value, size_t size)
359
+ {
360
+ using Intrinsic_T = typename detail::intrinsic_type<T>;
297
361
 
362
+ ruby_value_type valueType = rb_type(value);
298
363
  switch (valueType)
299
364
  {
300
365
  case RUBY_T_ARRAY:
301
366
  {
302
367
  Array outer(value);
368
+
369
+ // Allocate outer buffer
303
370
  this->m_size = outer.size();
304
- this->m_outer = new T * [this->m_size]();
371
+ this->m_buffer = new T*[this->m_size]();
305
372
 
306
373
  for (size_t i = 0; i < this->m_size; i++)
307
374
  {
308
375
  // Check the inner value is also an array
309
376
  Array inner(outer[i].value());
310
377
 
311
- // Wrap it with a buffer and add it our list of inner buffers
312
- Buffer<T> buffer(inner.value());
313
-
314
- // And update the outer array
315
- this->m_outer[i] = buffer.ptr();
316
-
317
- // Now move the buffer into the affer, not the buffer pointer is still valid (it just got moved)
318
- this->m_inner.push_back(std::move(buffer));
378
+ // Allocate inner buffer
379
+ this->m_buffer[i] = new T[inner.size()]();
380
+
381
+ if constexpr (std::is_fundamental_v<Intrinsic_T>)
382
+ {
383
+ String packed = inner.pack<Intrinsic_T>();
384
+ memcpy((void*)this->m_buffer[i], RSTRING_PTR(packed.value()), RSTRING_LEN(packed.value()));
385
+ }
386
+ else
387
+ {
388
+ detail::From_Ruby<Intrinsic_T*> fromRuby;
389
+ for (int i = 0; i < inner.size(); i++)
390
+ {
391
+ this->m_buffer[0] = fromRuby.convert(inner[i].value());
392
+ }
393
+ }
319
394
  }
320
395
 
321
396
  this->m_owner = true;
322
397
  break;
323
398
  }
399
+ case RUBY_T_DATA:
400
+ {
401
+ if (Data_Type<Pointer<T*>>::is_descendant(value))
402
+ {
403
+ this->m_buffer = detail::unwrap<T*>(value, Data_Type<Pointer<T*>>::ruby_data_type(), false);
404
+ this->m_owner = false;
405
+ this->m_size = size;
406
+ break;
407
+ }
408
+ [[fallthrough]];
409
+ }
324
410
  default:
325
411
  {
326
- std::string typeName = detail::typeName(typeid(T));
412
+ detail::TypeMapper<T> typeMapper;
413
+ std::string typeName = typeMapper.name();
327
414
  throw Exception(rb_eTypeError, "wrong argument type %s (expected % s*)",
328
415
  detail::protect(rb_obj_classname, value), typeName.c_str());
329
416
  }
@@ -335,16 +422,20 @@ namespace Rice
335
422
  {
336
423
  if (this->m_owner)
337
424
  {
338
- delete[] this->m_outer;
425
+ for (size_t i = 0; i < this->m_size; i++)
426
+ {
427
+ delete this->m_buffer[i];
428
+ }
429
+
430
+ delete[] this->m_buffer;
339
431
  }
340
432
  }
341
433
 
342
434
  template <typename T>
343
435
  inline Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::Buffer(Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>&& other) : m_owner(other.m_owner), m_size(other.m_size),
344
- m_outer(other.m_outer), m_inner(std::move(other.m_inner))
436
+ m_buffer(other.m_buffer)
345
437
  {
346
- other.m_outer = nullptr;
347
- other.m_inner.clear();
438
+ other.m_buffer = nullptr;
348
439
  other.m_size = 0;
349
440
  other.m_owner = false;
350
441
  }
@@ -352,11 +443,8 @@ namespace Rice
352
443
  template <typename T>
353
444
  inline Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>& Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::operator=(Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>&& other)
354
445
  {
355
- this->m_outer = other.m_outer;
356
- other.m_outer = nullptr;
357
-
358
- this->m_inner = std::move(other.m_inner);
359
- other.m_inner.clear();
446
+ this->m_buffer = other.m_buffer;
447
+ other.m_buffer = nullptr;
360
448
 
361
449
  this->m_size = other.m_size;
362
450
  other.m_size = 0;
@@ -368,9 +456,9 @@ namespace Rice
368
456
  }
369
457
 
370
458
  template <typename T>
371
- inline typename Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::Element_T& Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::operator[](size_t index)
459
+ inline T* Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::operator[](size_t index)
372
460
  {
373
- return this->m_inner[index];
461
+ return this->m_buffer[index];
374
462
  }
375
463
 
376
464
  template <typename T>
@@ -380,15 +468,16 @@ namespace Rice
380
468
  }
381
469
 
382
470
  template <typename T>
383
- void Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::setSize(size_t value)
471
+ inline T** Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::ptr()
384
472
  {
385
- this->m_size = value;
473
+ return this->m_buffer;
386
474
  }
387
475
 
388
476
  template <typename T>
389
- inline T** Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::ptr()
477
+ inline T** Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::release()
390
478
  {
391
- return this->m_outer;
479
+ this->m_owner = false;
480
+ return this->m_buffer;
392
481
  }
393
482
 
394
483
  template <typename T>
@@ -403,17 +492,11 @@ namespace Rice
403
492
  this->m_owner = value;
404
493
  }
405
494
 
406
- template <typename T>
407
- inline void Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::release()
408
- {
409
- this->m_owner = false;
410
- }
411
-
412
495
  template<typename T>
413
496
  inline VALUE Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::toString() const
414
497
  {
415
- std::string name = detail::typeName(typeid(T*));
416
- std::string description = "Buffer<type: " + detail::cppClassName(name) + ", size: " + std::to_string(this->m_size) + ">";
498
+ detail::TypeMapper<T*> typeMapper;
499
+ std::string description = "Buffer<type: " + typeMapper.simplifiedName() + ", size: " + std::to_string(this->m_size) + ">";
417
500
 
418
501
  // We can't use To_Ruby because To_Ruby depends on Buffer - ie a circular reference
419
502
  return detail::protect(rb_utf8_str_new_cstr, description.c_str());
@@ -422,13 +505,13 @@ namespace Rice
422
505
  template<typename T>
423
506
  inline VALUE Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::bytes(size_t count) const
424
507
  {
425
- if (!this->m_outer)
508
+ if (!this->m_buffer)
426
509
  {
427
510
  return Qnil;
428
511
  }
429
512
  else
430
513
  {
431
- T** begin = this->m_outer;
514
+ T** begin = this->m_buffer;
432
515
  long length = (long)(count * sizeof(T*));
433
516
  return detail::protect(rb_str_new_static, (const char*)*begin, length);
434
517
  }
@@ -443,7 +526,7 @@ namespace Rice
443
526
  template<typename T>
444
527
  inline Array Buffer<T*, std::enable_if_t<!detail::is_wrapped_v<T>>>::toArray(size_t count) const
445
528
  {
446
- if (!this->m_outer)
529
+ if (!this->m_buffer)
447
530
  {
448
531
  return Qnil;
449
532
  }
@@ -451,13 +534,13 @@ namespace Rice
451
534
  {
452
535
  Array result;
453
536
 
454
- T** ptr = this->m_outer;
455
- T** end = this->m_outer + count;
537
+ T** ptr = this->m_buffer;
538
+ T** end = this->m_buffer + count;
456
539
 
457
540
  for (; ptr < end; ptr++)
458
541
  {
459
542
  Buffer<T> buffer(*ptr);
460
- result.push(std::move(buffer));
543
+ result.push(std::move(buffer), true);
461
544
  }
462
545
  return result;
463
546
  }
@@ -481,10 +564,14 @@ namespace Rice
481
564
  }
482
565
 
483
566
  template <typename T>
484
- inline Buffer<T*, std::enable_if_t<detail::is_wrapped_v<T>>>::Buffer(VALUE value)
567
+ inline Buffer<T*, std::enable_if_t<detail::is_wrapped_v<T>>>::Buffer(VALUE value) : Buffer(value, 0)
568
+ {
569
+ }
570
+
571
+ template <typename T>
572
+ inline Buffer<T*, std::enable_if_t<detail::is_wrapped_v<T>>>::Buffer(VALUE value, size_t size)
485
573
  {
486
574
  ruby_value_type valueType = rb_type(value);
487
-
488
575
  switch (valueType)
489
576
  {
490
577
  case RUBY_T_ARRAY:
@@ -493,19 +580,30 @@ namespace Rice
493
580
  this->m_size = array.size();
494
581
  this->m_buffer = new T * [this->m_size]();
495
582
 
496
- detail::From_Ruby<T> fromRuby;
583
+ detail::From_Ruby<T*> fromRuby;
584
+
497
585
  for (size_t i = 0; i < this->m_size; i++)
498
586
  {
499
- Data_Object<detail::intrinsic_type<T>> dataObject(array[i].value());
500
- this->m_buffer[i] = dataObject.get();
587
+ this->m_buffer[i] = fromRuby.convert(array[i].value());
501
588
  }
502
589
 
503
590
  this->m_owner = true;
504
591
  break;
505
592
  }
593
+ case RUBY_T_DATA:
594
+ {
595
+ if (Data_Type<Pointer<T*>>::is_descendant(value))
596
+ {
597
+ this->m_buffer = detail::unwrap<T*>(value, Data_Type<Pointer<T*>>::ruby_data_type(), false);
598
+ this->m_owner = false;
599
+ this->m_size = size;
600
+ break;
601
+ }
602
+ }
506
603
  default:
507
604
  {
508
- std::string typeName = detail::typeName(typeid(T));
605
+ detail::TypeMapper<T> typeMapper;
606
+ std::string typeName = typeMapper.name();
509
607
  throw Exception(rb_eTypeError, "wrong argument type %s (expected % s*)",
510
608
  detail::protect(rb_obj_classname, value), typeName.c_str());
511
609
  }
@@ -546,7 +644,7 @@ namespace Rice
546
644
  }
547
645
 
548
646
  template <typename T>
549
- inline typename Buffer<T*, std::enable_if_t<detail::is_wrapped_v<T>>>::Element_T& Buffer<T*, std::enable_if_t<detail::is_wrapped_v<T>>>::operator[](size_t index)
647
+ inline T* Buffer<T*, std::enable_if_t<detail::is_wrapped_v<T>>>::operator[](size_t index)
550
648
  {
551
649
  if (index >= this->m_size)
552
650
  {
@@ -562,14 +660,15 @@ namespace Rice
562
660
  }
563
661
 
564
662
  template <typename T>
565
- void Buffer<T*, std::enable_if_t<detail::is_wrapped_v<T>>>::setSize(size_t value)
663
+ inline T** Buffer<T*, std::enable_if_t<detail::is_wrapped_v<T>>>::ptr()
566
664
  {
567
- this->m_size = value;
665
+ return this->m_buffer;
568
666
  }
569
667
 
570
668
  template <typename T>
571
- inline T** Buffer<T*, std::enable_if_t<detail::is_wrapped_v<T>>>::ptr()
669
+ inline T** Buffer<T*, std::enable_if_t<detail::is_wrapped_v<T>>>::release()
572
670
  {
671
+ this->m_owner = false;
573
672
  return this->m_buffer;
574
673
  }
575
674
 
@@ -585,17 +684,11 @@ namespace Rice
585
684
  this->m_owner = value;
586
685
  }
587
686
 
588
- template <typename T>
589
- inline void Buffer<T*, std::enable_if_t<detail::is_wrapped_v<T>>>::release()
590
- {
591
- this->m_owner = false;
592
- }
593
-
594
687
  template<typename T>
595
688
  inline VALUE Buffer<T*, std::enable_if_t<detail::is_wrapped_v<T>>>::toString() const
596
689
  {
597
- std::string name = detail::typeName(typeid(T*));
598
- std::string description = "Buffer<type: " + detail::cppClassName(name) + ", size: " + std::to_string(this->m_size) + ">";
690
+ detail::TypeMapper<T*> typeMapper;
691
+ std::string description = "Buffer<type: " + typeMapper.simplifiedName() + ", size: " + std::to_string(this->m_size) + ">";
599
692
 
600
693
  // We can't use To_Ruby because To_Ruby depends on Buffer - ie a circular reference
601
694
  return detail::protect(rb_utf8_str_new_cstr, description.c_str());
@@ -638,7 +731,7 @@ namespace Rice
638
731
 
639
732
  for (; ptr < end; ptr++)
640
733
  {
641
- result.push(*ptr);
734
+ result.push(*ptr, false);
642
735
  }
643
736
  return result;
644
737
  }
@@ -651,16 +744,52 @@ namespace Rice
651
744
  }
652
745
 
653
746
  // ---- Buffer<void> -------
654
- inline Buffer<void>::Buffer(void* pointer) : m_buffer(pointer)
747
+ template<typename T>
748
+ inline Buffer<T, std::enable_if_t<std::is_void_v<T>>>::Buffer(VALUE value) : Buffer(value, 0)
749
+ {
750
+ }
751
+
752
+ template<typename T>
753
+ inline Buffer<T, std::enable_if_t<std::is_void_v<T>>>::Buffer(VALUE value, size_t size)
754
+ {
755
+ ruby_value_type valueType = rb_type(value);
756
+
757
+ switch (valueType)
758
+ {
759
+ case RUBY_T_STRING:
760
+ {
761
+ this->m_size = RSTRING_LEN(value);
762
+ this->m_buffer = ::operator new(this->m_size);
763
+ memcpy((void*)this->m_buffer, RSTRING_PTR(value), this->m_size);
764
+
765
+ this->m_owner = true;
766
+ break;
767
+ }
768
+ default:
769
+ {
770
+ detail::TypeMapper<void> typeMapper;
771
+ std::string typeName = typeMapper.name();
772
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected % s*)",
773
+ detail::protect(rb_obj_classname, value), typeName.c_str());
774
+ }
775
+ }
776
+ }
777
+
778
+ template<typename T>
779
+ inline Buffer<T, std::enable_if_t<std::is_void_v<T>>>::Buffer(T* pointer) : m_buffer(pointer)
655
780
  {
656
781
  }
657
782
 
658
- inline Buffer<void>::Buffer(Buffer<void>&& other) : m_buffer(other.m_buffer)
783
+ template<typename T>
784
+ inline Buffer<T, std::enable_if_t<std::is_void_v<T>>>::Buffer(Buffer<T, std::enable_if_t<std::is_void_v<T>>>&& other) : m_owner(other.m_owner), m_size(other.m_size), m_buffer(other.m_buffer)
659
785
  {
660
786
  other.m_buffer = nullptr;
787
+ other.m_size = 0;
788
+ other.m_owner = false;
661
789
  }
662
790
 
663
- inline Buffer<void>& Buffer<void>::operator=(Buffer<void>&& other)
791
+ template<typename T>
792
+ inline Buffer<T, std::enable_if_t<std::is_void_v<T>>>& Buffer<T, std::enable_if_t<std::is_void_v<T>>>::operator=(Buffer<T, std::enable_if_t<std::is_void_v<T>>>&& other)
664
793
  {
665
794
  this->m_buffer = other.m_buffer;
666
795
  other.m_buffer = nullptr;
@@ -668,104 +797,108 @@ namespace Rice
668
797
  return *this;
669
798
  }
670
799
 
671
- inline void* Buffer<void>::ptr()
800
+ template<typename T>
801
+ inline size_t Buffer<T, std::enable_if_t<std::is_void_v<T>>>::size() const
672
802
  {
803
+ return this->m_size;
804
+ }
805
+
806
+ template<typename T>
807
+ inline T* Buffer<T, std::enable_if_t<std::is_void_v<T>>>::ptr()
808
+ {
809
+ return this->m_buffer;
810
+ }
811
+
812
+ template <typename T>
813
+ inline T* Buffer<T, std::enable_if_t<std::is_void_v<T>>>::release()
814
+ {
815
+ this->m_owner = false;
673
816
  return this->m_buffer;
674
817
  }
675
818
 
819
+ template<typename T>
820
+ inline VALUE Buffer<T, std::enable_if_t<std::is_void_v<T>>>::bytes(size_t count) const
821
+ {
822
+ if (!this->m_buffer)
823
+ {
824
+ return Qnil;
825
+ }
826
+ else
827
+ {
828
+ return detail::protect(rb_usascii_str_new, (const char*)this->m_buffer, (long)count);
829
+ }
830
+ }
831
+
832
+ template<typename T>
833
+ inline VALUE Buffer<T, std::enable_if_t<std::is_void_v<T>>>::bytes() const
834
+ {
835
+ return this->bytes(this->m_size);
836
+ }
837
+
676
838
  // ------ define_buffer ----------
677
839
  template<typename T>
678
840
  inline Data_Type<Buffer<T>> define_buffer(std::string klassName)
679
841
  {
680
842
  using Buffer_T = Buffer<T>;
843
+ using Data_Type_T = Data_Type<Buffer_T>;
681
844
 
682
845
  if (klassName.empty())
683
846
  {
684
- std::string typeName = detail::typeName(typeid(Buffer_T));
685
- // This will end up as Buffer<T,void>. We want to remove the ,void part.
686
- auto removeVoidRegex = std::regex(",\\s?void");
687
- typeName = std::regex_replace(typeName, removeVoidRegex, "");
688
- klassName = detail::rubyClassName(typeName);
847
+ detail::TypeMapper<Buffer_T> typeMapper;
848
+ klassName = typeMapper.rubyName();
689
849
  }
690
850
 
691
851
  Module rb_mRice = define_module("Rice");
692
852
 
853
+ if (Data_Type_T::check_defined(klassName, rb_mRice))
854
+ {
855
+ return Data_Type_T();
856
+ }
857
+
693
858
  if constexpr (std::is_void_v<T>)
694
859
  {
695
- return define_class_under<Buffer_T>(rb_mRice, klassName);
860
+ return define_class_under<Buffer_T>(rb_mRice, klassName).
861
+ define_constructor(Constructor<Buffer_T, VALUE>(), Arg("value").setValue()).
862
+ define_constructor(Constructor<Buffer_T, VALUE, size_t>(), Arg("value").setValue(), Arg("size")).
863
+ define_method("size", &Buffer_T::size).
864
+ template define_method<VALUE(Buffer_T::*)(size_t) const>("bytes", &Buffer_T::bytes, Return().setValue()).
865
+ template define_method<VALUE(Buffer_T::*)() const>("bytes", &Buffer_T::bytes, Return().setValue()).
866
+ define_method("data", &Buffer_T::ptr, Return().setBuffer()).
867
+ define_method("release", &Buffer_T::release, Return().setBuffer());
696
868
  }
697
869
  else
698
870
  {
699
871
  Data_Type<Buffer_T> klass = define_class_under<Buffer_T>(rb_mRice, klassName).
700
872
  define_constructor(Constructor<Buffer_T, VALUE>(), Arg("value").setValue()).
873
+ define_constructor(Constructor<Buffer_T, VALUE, size_t>(), Arg("value").setValue(), Arg("size")).
701
874
  define_method("size", &Buffer_T::size).
702
- define_method("size=", &Buffer_T::setSize).
703
875
  template define_method<VALUE(Buffer_T::*)() const>("to_s", &Buffer_T::toString, Return().setValue()).
704
876
  template define_method<VALUE(Buffer_T::*)(size_t) const>("bytes", &Buffer_T::bytes, Return().setValue()).
705
877
  template define_method<VALUE(Buffer_T::*)() const>("bytes", &Buffer_T::bytes, Return().setValue()).
706
878
  template define_method<Array(Buffer_T::*)(size_t) const>("to_ary", &Buffer_T::toArray, Return().setValue()).
707
- template define_method<Array(Buffer_T::*)() const>("to_ary", &Buffer_T::toArray, Return().setValue());
879
+ template define_method<Array(Buffer_T::*)() const>("to_ary", &Buffer_T::toArray, Return().setValue()).
880
+ define_method("[]", &Buffer_T::operator[], Arg("index")).
881
+ define_method("data", &Buffer_T::ptr, Return().setBuffer()).
882
+ define_method("release", &Buffer_T::release, Return().setBuffer());
708
883
 
709
- klass.
710
- define_method("[]", &Buffer_T::operator[], Arg("index"));
711
-
712
- if constexpr (std::is_pointer_v<T> && detail::is_wrapped_v<T>)
713
- {
714
- klass.define_method("[]=", [](Buffer_T& self, size_t index, typename Buffer_T::Element_T element) -> void
715
- {
716
- self[index] = element;
717
- });
718
- }
719
- else if constexpr (std::is_pointer_v<T> && !detail::is_wrapped_v<T>)
884
+ if constexpr (!std::is_pointer_v<T> && !std::is_void_v<T> && !std::is_const_v<T> && std::is_copy_assignable_v<T>)
720
885
  {
721
- klass.define_method("[]=", [](Buffer_T& self, size_t index, typename Buffer_T::Element_T& element) -> void
886
+ klass.define_method("[]=", [](Buffer_T& self, size_t index, T& value) -> void
722
887
  {
723
- self[index] = std::move(element);
888
+ self[index] = value;
724
889
  });
725
890
  }
726
- else
891
+ else if constexpr (std::is_pointer_v<T> && !std::is_const_v<std::remove_pointer_t<T>> && std::is_copy_assignable_v<std::remove_pointer_t<T>>)
727
892
  {
728
- klass.define_method("[]=", [](Buffer_T& self, size_t index, typename Buffer_T::Element_T& element) -> void
893
+ klass.define_method("[]=", [](Buffer_T& self, size_t index, T value) -> void
729
894
  {
730
- self[index] = element;
895
+ *self[index] = *value;
731
896
  });
732
897
  }
733
898
 
734
899
  return klass;
735
900
  }
736
901
  }
737
-
738
- inline void define_fundamental_buffer_types()
739
- {
740
- define_buffer<bool>();
741
- define_buffer<int>();
742
- define_buffer<int*>();
743
- define_buffer<unsigned int>();
744
- define_buffer<unsigned int*>();
745
- define_buffer<char>();
746
- define_buffer<char*>();
747
- define_buffer<unsigned char>();
748
- define_buffer<unsigned char*>();
749
- define_buffer<signed char>();
750
- define_buffer<signed char*>();
751
- define_buffer<double>();
752
- define_buffer<double*>();
753
- define_buffer<float>();
754
- define_buffer<float*>();
755
- define_buffer<long>();
756
- define_buffer<long*>();
757
- define_buffer<unsigned long>();
758
- define_buffer<unsigned long*>();
759
- define_buffer<long long>();
760
- define_buffer<long long*>();
761
- define_buffer<unsigned long long>();
762
- define_buffer<unsigned long long*>();
763
- define_buffer<short>();
764
- define_buffer<short*>();
765
- define_buffer<unsigned short>();
766
- define_buffer<unsigned short*>();
767
- define_buffer<void>();
768
- }
769
902
  }
770
903
 
771
904
  namespace Rice::detail
@@ -775,13 +908,8 @@ namespace Rice::detail
775
908
  {
776
909
  static bool verify()
777
910
  {
778
- Type<intrinsic_type<T>>::verify();
779
-
780
- if (!Data_Type<Buffer<T>>::is_defined())
781
- {
782
- define_buffer<T>();
783
- }
784
-
911
+ detail::verifyType<T>();
912
+ define_buffer<T>();
785
913
  return true;
786
914
  }
787
915
  };