rice 4.7.0 → 4.8.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 (155) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +36 -1
  3. data/CMakeLists.txt +14 -22
  4. data/CMakePresets.json +203 -75
  5. data/FindRuby.cmake +358 -123
  6. data/bin/rice-doc.rb +56 -142
  7. data/bin/rice-rbs.rb +1 -2
  8. data/include/rice/api.hpp +248 -0
  9. data/include/rice/rice.hpp +2281 -1668
  10. data/include/rice/stl.hpp +364 -443
  11. data/lib/rice/doc/config.rb +70 -0
  12. data/lib/rice/doc/cpp_reference.rb +1 -4
  13. data/lib/rice/doc/mkdocs.rb +58 -20
  14. data/lib/rice/doc/rice.rb +20 -0
  15. data/lib/rice/doc.rb +1 -0
  16. data/lib/rice/make_rice_headers.rb +7 -0
  17. data/lib/rice/native_registry.rb +2 -2
  18. data/lib/rice/rbs.rb +4 -4
  19. data/lib/rice/version.rb +1 -1
  20. data/lib/rubygems_plugin.rb +12 -9
  21. data/rice/Arg.hpp +12 -6
  22. data/rice/Arg.ipp +14 -7
  23. data/rice/Buffer.ipp +44 -40
  24. data/rice/Callback.hpp +1 -1
  25. data/rice/Callback.ipp +2 -7
  26. data/rice/Constructor.hpp +1 -1
  27. data/rice/Constructor.ipp +11 -11
  28. data/rice/Data_Object.ipp +59 -30
  29. data/rice/Data_Type.hpp +9 -10
  30. data/rice/Data_Type.ipp +22 -25
  31. data/rice/Director.hpp +1 -0
  32. data/rice/Enum.ipp +58 -39
  33. data/rice/Exception.hpp +4 -4
  34. data/rice/Exception.ipp +7 -7
  35. data/rice/NoGVL.hpp +13 -0
  36. data/rice/Reference.hpp +56 -0
  37. data/rice/Reference.ipp +96 -0
  38. data/rice/Return.hpp +4 -1
  39. data/rice/Return.ipp +0 -6
  40. data/rice/cpp_api/Array.hpp +44 -7
  41. data/rice/cpp_api/Array.ipp +105 -9
  42. data/rice/cpp_api/Class.hpp +2 -2
  43. data/rice/cpp_api/Class.ipp +4 -4
  44. data/rice/cpp_api/Hash.ipp +7 -4
  45. data/rice/cpp_api/Module.hpp +4 -4
  46. data/rice/cpp_api/Module.ipp +12 -10
  47. data/rice/cpp_api/Object.hpp +4 -4
  48. data/rice/cpp_api/Object.ipp +15 -12
  49. data/rice/cpp_api/String.hpp +2 -2
  50. data/rice/cpp_api/String.ipp +11 -8
  51. data/rice/cpp_api/Symbol.ipp +16 -7
  52. data/rice/cpp_api/shared_methods.hpp +5 -9
  53. data/rice/detail/InstanceRegistry.hpp +0 -2
  54. data/rice/detail/Native.hpp +31 -21
  55. data/rice/detail/Native.ipp +281 -133
  56. data/rice/detail/NativeAttributeGet.hpp +5 -7
  57. data/rice/detail/NativeAttributeGet.ipp +26 -26
  58. data/rice/detail/NativeAttributeSet.hpp +2 -4
  59. data/rice/detail/NativeAttributeSet.ipp +20 -16
  60. data/rice/detail/NativeCallback.hpp +77 -0
  61. data/rice/detail/NativeCallback.ipp +280 -0
  62. data/rice/detail/NativeFunction.hpp +11 -21
  63. data/rice/detail/NativeFunction.ipp +58 -119
  64. data/rice/detail/NativeInvoker.hpp +4 -4
  65. data/rice/detail/NativeInvoker.ipp +7 -7
  66. data/rice/detail/NativeIterator.hpp +2 -4
  67. data/rice/detail/NativeIterator.ipp +18 -14
  68. data/rice/detail/NativeMethod.hpp +10 -20
  69. data/rice/detail/NativeMethod.ipp +54 -114
  70. data/rice/detail/NativeProc.hpp +5 -7
  71. data/rice/detail/NativeProc.ipp +39 -28
  72. data/rice/detail/NativeRegistry.hpp +0 -1
  73. data/rice/detail/NativeRegistry.ipp +0 -1
  74. data/rice/detail/Parameter.hpp +15 -8
  75. data/rice/detail/Parameter.ipp +102 -43
  76. data/rice/detail/Proc.ipp +14 -28
  77. data/rice/detail/RubyType.ipp +2 -53
  78. data/rice/detail/Type.hpp +23 -7
  79. data/rice/detail/Type.ipp +73 -93
  80. data/rice/detail/TypeRegistry.ipp +5 -4
  81. data/rice/detail/Wrapper.hpp +1 -1
  82. data/rice/detail/Wrapper.ipp +18 -10
  83. data/rice/detail/from_ruby.hpp +8 -6
  84. data/rice/detail/from_ruby.ipp +306 -173
  85. data/rice/detail/ruby.hpp +23 -0
  86. data/rice/libc/file.hpp +4 -4
  87. data/rice/rice.hpp +6 -8
  88. data/rice/rice_api/Native.ipp +5 -1
  89. data/rice/rice_api/Parameter.ipp +1 -1
  90. data/rice/ruby_mark.hpp +2 -1
  91. data/rice/stl/complex.ipp +12 -8
  92. data/rice/stl/map.ipp +27 -22
  93. data/rice/stl/monostate.ipp +16 -12
  94. data/rice/stl/multimap.hpp +0 -2
  95. data/rice/stl/multimap.ipp +27 -22
  96. data/rice/stl/optional.ipp +27 -11
  97. data/rice/stl/pair.ipp +5 -5
  98. data/rice/stl/reference_wrapper.ipp +5 -4
  99. data/rice/stl/set.ipp +16 -16
  100. data/rice/stl/shared_ptr.hpp +0 -16
  101. data/rice/stl/shared_ptr.ipp +34 -190
  102. data/rice/stl/string.ipp +18 -18
  103. data/rice/stl/string_view.ipp +19 -1
  104. data/rice/stl/tuple.ipp +15 -36
  105. data/rice/stl/unique_ptr.ipp +18 -8
  106. data/rice/stl/unordered_map.ipp +20 -15
  107. data/rice/stl/variant.ipp +37 -21
  108. data/rice/stl/vector.ipp +41 -36
  109. data/rice/traits/function_traits.hpp +19 -19
  110. data/rice/traits/method_traits.hpp +4 -4
  111. data/rice/traits/rice_traits.hpp +162 -39
  112. data/rice.gemspec +1 -4
  113. data/test/test_Array.cpp +261 -3
  114. data/test/test_Attribute.cpp +6 -3
  115. data/test/test_Buffer.cpp +6 -42
  116. data/test/test_Callback.cpp +77 -23
  117. data/test/test_Data_Object.cpp +2 -2
  118. data/test/test_Data_Type.cpp +23 -23
  119. data/test/test_Director.cpp +2 -4
  120. data/test/test_Enum.cpp +34 -5
  121. data/test/test_File.cpp +9 -5
  122. data/test/test_From_Ruby.cpp +7 -6
  123. data/test/test_GVL.cpp +3 -3
  124. data/test/test_Hash.cpp +1 -1
  125. data/test/test_Iterator.cpp +54 -22
  126. data/test/test_Keep_Alive.cpp +1 -1
  127. data/test/test_Keep_Alive_No_Wrapper.cpp +1 -1
  128. data/test/test_Module.cpp +5 -5
  129. data/test/test_Overloads.cpp +395 -50
  130. data/test/test_Proc.cpp +54 -0
  131. data/test/test_Reference.cpp +181 -0
  132. data/test/test_Self.cpp +2 -2
  133. data/test/test_Stl_Set.cpp +6 -6
  134. data/test/test_Stl_SharedPtr.cpp +54 -30
  135. data/test/test_Stl_String_View.cpp +12 -0
  136. data/test/test_Stl_Tuple.cpp +1 -1
  137. data/test/test_Stl_Variant.cpp +6 -14
  138. data/test/test_Stl_Vector.cpp +61 -30
  139. data/test/test_String.cpp +4 -2
  140. data/test/test_Struct.cpp +1 -1
  141. data/test/test_Symbol.cpp +12 -0
  142. data/test/test_To_Ruby.cpp +1 -0
  143. data/test/test_Type.cpp +36 -35
  144. data/test/test_global_functions.cpp +1 -1
  145. data/test/unittest.cpp +1 -1
  146. data/test/unittest.hpp +5 -5
  147. metadata +10 -24
  148. data/rice/Function.hpp +0 -17
  149. data/rice/Function.ipp +0 -13
  150. data/rice/detail/MethodInfo.hpp +0 -48
  151. data/rice/detail/MethodInfo.ipp +0 -99
  152. data/rice/detail/NativeCallbackFFI.hpp +0 -55
  153. data/rice/detail/NativeCallbackFFI.ipp +0 -152
  154. data/rice/detail/NativeCallbackSimple.hpp +0 -30
  155. data/rice/detail/NativeCallbackSimple.ipp +0 -29
data/rice/Data_Type.ipp CHANGED
@@ -20,13 +20,13 @@ namespace Rice
20
20
  }
21
21
 
22
22
  template<typename T>
23
- inline size_t ruby_size_internal(const T* data)
23
+ inline size_t ruby_size_internal(const T*)
24
24
  {
25
25
  return sizeof(T);
26
26
  }
27
27
 
28
28
  template<>
29
- inline size_t ruby_size_internal(const void* data)
29
+ inline size_t ruby_size_internal(const void*)
30
30
  {
31
31
  return sizeof(void*);
32
32
  }
@@ -37,8 +37,8 @@ namespace Rice
37
37
  {
38
38
  if (is_bound())
39
39
  {
40
- detail::TypeMapper<T> typeMapper;
41
- std::string message = "Type " + typeMapper.name() + " is already bound to a different type";
40
+ detail::TypeIndexParser typeIndexParser(typeid(T), std::is_fundamental_v<detail::intrinsic_type<T>>);
41
+ std::string message = "Type " + typeIndexParser.name() + " is already bound to a different type";
42
42
  throw std::runtime_error(message.c_str());
43
43
  }
44
44
 
@@ -69,10 +69,10 @@ namespace Rice
69
69
 
70
70
  // Add a method to get the source C++ class name from Ruby
71
71
  Data_Type<T> dataType;
72
- dataType.define_singleton_method("cpp_class", [](VALUE klass) -> VALUE
72
+ dataType.define_singleton_method("cpp_class", [](VALUE) -> VALUE
73
73
  {
74
- detail::TypeMapper<T> typeMapper;
75
- std::string cppClassName = typeMapper.simplifiedName();
74
+ detail::TypeIndexParser typeIndexParser(typeid(T), std::is_fundamental_v<detail::intrinsic_type<T>>);
75
+ std::string cppClassName = typeIndexParser.simplifiedName();
76
76
  Return returnInfo;
77
77
  returnInfo.takeOwnership();
78
78
  return detail::To_Ruby<char*>(&returnInfo).convert(cppClassName.c_str());
@@ -148,7 +148,7 @@ namespace Rice
148
148
 
149
149
  template<typename T>
150
150
  template<typename Constructor_T, typename...Rice_Arg_Ts>
151
- inline Data_Type<T>& Data_Type<T>::define_constructor(Constructor_T constructor, Rice_Arg_Ts const& ...args)
151
+ inline Data_Type<T>& Data_Type<T>::define_constructor(Constructor_T, Rice_Arg_Ts const& ...args)
152
152
  {
153
153
  check_is_bound();
154
154
 
@@ -187,9 +187,6 @@ namespace Rice
187
187
  template<typename Function_T>
188
188
  inline Data_Type<T>& Data_Type<T>::define(Function_T func)
189
189
  {
190
- // The passed in this pointer is an RValue, so we need to keep it alive by
191
- // assigning it to a const lvalue
192
- const auto& dummy = *this;
193
190
  func(*this);
194
191
  return *this;
195
192
  }
@@ -233,8 +230,8 @@ namespace Rice
233
230
  {
234
231
  if (!is_bound())
235
232
  {
236
- detail::TypeMapper<T> typeMapper;
237
- std::string message = "Type is not defined with Rice: " + typeMapper.name();
233
+ detail::TypeIndexParser typeIndexParser(typeid(T), std::is_fundamental_v<detail::intrinsic_type<T>>);
234
+ std::string message = "Type is not defined with Rice: " + typeIndexParser.name();
238
235
  throw std::invalid_argument(message.c_str());
239
236
  }
240
237
  }
@@ -330,30 +327,30 @@ namespace Rice
330
327
  }
331
328
 
332
329
  template <typename T>
333
- template <typename Attribute_T>
334
- inline Data_Type<T>& Data_Type<T>::define_attr(std::string name, Attribute_T attribute, AttrAccess access, Return returnInfo)
330
+ template <typename Attribute_T, typename...Arg_Ts>
331
+ inline Data_Type<T>& Data_Type<T>::define_attr(std::string name, Attribute_T attribute, AttrAccess access, const Arg_Ts&...args)
335
332
  {
336
- return this->define_attr_internal<Attribute_T>(this->klass_, name, std::forward<Attribute_T>(attribute), access, returnInfo);
333
+ return this->define_attr_internal<Attribute_T>(this->klass_, name, std::forward<Attribute_T>(attribute), access, args...);
337
334
  }
338
335
 
339
336
  template <typename T>
340
- template <typename Attribute_T>
341
- inline Data_Type<T>& Data_Type<T>::define_singleton_attr(std::string name, Attribute_T attribute, AttrAccess access, Return returnInfo)
337
+ template <typename Attribute_T, typename...Arg_Ts>
338
+ inline Data_Type<T>& Data_Type<T>::define_singleton_attr(std::string name, Attribute_T attribute, AttrAccess access, const Arg_Ts&...args)
342
339
  {
343
340
  VALUE singleton = detail::protect(rb_singleton_class, this->value());
344
- return this->define_attr_internal<Attribute_T>(singleton, name, std::forward<Attribute_T>(attribute), access, returnInfo);
341
+ return this->define_attr_internal<Attribute_T>(singleton, name, std::forward<Attribute_T>(attribute), access, args...);
345
342
  }
346
343
 
347
344
  template <typename T>
348
- template <typename Attribute_T>
349
- inline Data_Type<T>& Data_Type<T>::define_attr_internal(VALUE klass, std::string name, Attribute_T attribute, AttrAccess access, Return returnInfo)
345
+ template <typename Attribute_T, typename...Arg_Ts>
346
+ inline Data_Type<T>& Data_Type<T>::define_attr_internal(VALUE klass, std::string name, Attribute_T attribute, AttrAccess access, const Arg_Ts&...args)
350
347
  {
351
348
  using Attr_T = typename detail::attribute_traits<Attribute_T>::attr_type;
352
349
 
353
350
  // Define attribute getter
354
351
  if (access == AttrAccess::ReadWrite || access == AttrAccess::Read)
355
352
  {
356
- detail::NativeAttributeGet<Attribute_T>::define(klass, name, std::forward<Attribute_T>(attribute), returnInfo);
353
+ detail::NativeAttributeGet<Attribute_T>::define(klass, name, std::forward<Attribute_T>(attribute), args...);
357
354
  }
358
355
 
359
356
  // Define attribute setter
@@ -391,9 +388,9 @@ namespace Rice
391
388
  }
392
389
 
393
390
  template <typename T>
394
- template<typename Method_T>
395
- inline void Data_Type<T>::wrap_native_method(VALUE klass, std::string name, Method_T&& method, MethodInfo* methodInfo)
391
+ template<typename Method_T, typename ...Arg_Ts>
392
+ inline void Data_Type<T>::wrap_native_method(VALUE klass, std::string name, Method_T&& method, const Arg_Ts&...args)
396
393
  {
397
- Module::wrap_native_method<T, Method_T>(klass, name, std::forward<Method_T>(method), methodInfo);
394
+ Module::wrap_native_method<T, Method_T>(klass, name, std::forward<Method_T>(method), args...);
398
395
  }
399
396
  }
data/rice/Director.hpp CHANGED
@@ -23,6 +23,7 @@ namespace Rice
23
23
  /*! If a Ruby script calls 'super' on a method that's otherwise a pure virtual
24
24
  * method, use this method to throw an exception in this case.
25
25
  */
26
+ [[noreturn]]
26
27
  void raisePureVirtual() const
27
28
  {
28
29
  rb_raise(rb_eNotImpError, "Cannot call super() into a pure-virtual C++ method");
data/rice/Enum.ipp CHANGED
@@ -29,48 +29,52 @@ namespace Rice
29
29
  klass.define_constructor(Constructor<Enum_T>());
30
30
 
31
31
  klass.define_method("to_s", [](Enum_T& self) -> String
32
- {
33
- return String(valuesToNames_[self]);
34
- })
35
- .define_method("to_int", [](Enum_T& self) -> Underlying_T
36
- {
37
- return (Underlying_T)(self);
38
- })
39
- .define_method("coerce", [](Enum_T& self, Underlying_T& other) -> Array
40
- {
41
- /* Other will be a numeric value that matches the underlying type of the enum, for example an int.
42
- Convert that to the enum type and then create new Ruby object to wrap it. This then enables code
43
- like this:
32
+ {
33
+ return String(valuesToNames_[self]);
34
+ })
35
+ .define_method("to_int", [](Enum_T& self) -> Underlying_T
36
+ {
37
+ return (Underlying_T)(self);
38
+ })
39
+ .define_method("coerce", [](Enum_T& self, Underlying_T& other) -> Array
40
+ {
41
+ /* Other will be a numeric value that matches the underlying type of the enum, for example an int.
42
+ Convert that to the enum type and then create new Ruby object to wrap it. This then enables code
43
+ like this:
44
44
 
45
- Colors::Red | Colors:Blue | Colors:Green
45
+ Colors::Red | Colors:Blue | Colors:Green
46
46
 
47
- Colors::Red | Colors:Blue returns an integer. Then this method converts the integer back into an Enum
48
- instance so that Colors:Blue | Colors:Green works. */
49
- Enum_T otherEnum = (Enum_T)other;
47
+ Colors::Red | Colors:Blue returns an integer. Then this method converts the integer back into an Enum
48
+ instance so that Colors:Blue | Colors:Green works. */
49
+ Enum_T otherEnum = (Enum_T)other;
50
50
 
51
- Array result;
52
- result.push(self, false);
53
- result.push(otherEnum, true);
54
- return result;
55
- })
56
- .define_method("inspect", [](Enum_T& self)
57
- {
58
- std::stringstream result;
59
- VALUE rubyKlass = Enum<Enum_T>::klass().value();
60
- result << "#<" << detail::protect(rb_class2name, rubyKlass)
61
- << "::" << Enum<Enum_T>::valuesToNames_[self] << ">";
62
-
63
- // We have to return string because we don't know if std::string support has
64
- // been included by the user
65
- return String(result.str());
66
- })
67
- .define_method("hash", [](Enum_T& self) -> Underlying_T
68
- {
69
- return (Underlying_T)self;
70
- })
71
- .define_method("eql?", [](Enum_T& self, Enum_T& other)
72
- {
73
- return self == other;
51
+ Array result;
52
+ result.push(otherEnum, true);
53
+ result.push(self, false);
54
+ return result;
55
+ })
56
+ .define_method("inspect", [](Enum_T& self)
57
+ {
58
+ std::stringstream result;
59
+ VALUE rubyKlass = Enum<Enum_T>::klass().value();
60
+ result << "#<" << detail::protect(rb_class2name, rubyKlass)
61
+ << "::" << Enum<Enum_T>::valuesToNames_[self] << ">";
62
+
63
+ // We have to return string because we don't know if std::string support has
64
+ // been included by the user
65
+ return String(result.str());
66
+ })
67
+ .define_method("hash", [](Enum_T& self) -> Underlying_T
68
+ {
69
+ return (Underlying_T)self;
70
+ })
71
+ .define_method("eql?", [](Enum_T& self, Enum_T& other)
72
+ {
73
+ return self == other;
74
+ })
75
+ .define_method("eql?", [](Enum_T& self, Underlying_T& other)
76
+ {
77
+ return self == (Enum_T)other;
74
78
  });
75
79
 
76
80
  // Add aliases
@@ -93,6 +97,21 @@ namespace Rice
93
97
  {
94
98
  return 1;
95
99
  }
100
+ })
101
+ .define_method("<=>", [](Enum_T& self, Underlying_T& other)
102
+ {
103
+ if (self == (Enum_T)other)
104
+ {
105
+ return 0;
106
+ }
107
+ else if (self < (Enum_T)other)
108
+ {
109
+ return -1;
110
+ }
111
+ else
112
+ {
113
+ return 1;
114
+ }
96
115
  });
97
116
 
98
117
  // Add ability to get enum values
data/rice/Exception.hpp CHANGED
@@ -28,8 +28,8 @@ namespace Rice
28
28
  * \param fmt a printf-style format string
29
29
  * \param ... the arguments to the format string.
30
30
  */
31
- template <typename... Arg_Ts>
32
- Exception(const Exception& other, char const* fmt, Arg_Ts&&...args);
31
+ template <typename... Parameter_Ts>
32
+ Exception(const Exception& other, char const* fmt, Parameter_Ts&&...args);
33
33
 
34
34
  //! Construct a Exception with printf-style formatting.
35
35
  /*! \param exc either an exception object or a class that inherits
@@ -37,8 +37,8 @@ namespace Rice
37
37
  * \param fmt a printf-style format string
38
38
  * \param ... the arguments to the format string.
39
39
  */
40
- template <typename... Arg_Ts>
41
- Exception(const VALUE exceptionType, char const* fmt, Arg_Ts&&...args);
40
+ template <typename... Parameter_Ts>
41
+ Exception(const VALUE exceptionType, char const* fmt, Parameter_Ts&&...args);
42
42
 
43
43
  //! Destructor
44
44
  virtual ~Exception() noexcept = default;
data/rice/Exception.ipp CHANGED
@@ -5,27 +5,27 @@ namespace Rice
5
5
  {
6
6
  }
7
7
 
8
- template <typename... Arg_Ts>
9
- inline Exception::Exception(const Exception& other, char const* fmt, Arg_Ts&&...args)
10
- : Exception(other.class_of(), fmt, std::forward<Arg_Ts>(args)...)
8
+ template <typename... Parameter_Ts>
9
+ inline Exception::Exception(const Exception& other, char const* fmt, Parameter_Ts&&...args)
10
+ : Exception(other.class_of(), fmt, std::forward<Parameter_Ts>(args)...)
11
11
  {
12
12
  }
13
13
 
14
- template <typename... Arg_Ts>
15
- inline Exception::Exception(const VALUE exceptionClass, char const* fmt, Arg_Ts&&...args)
14
+ template <typename... Parameter_Ts>
15
+ inline Exception::Exception(const VALUE exceptionClass, char const* fmt, Parameter_Ts&&...args)
16
16
  {
17
17
  #if defined(__GNUC__) || defined(__clang__)
18
18
  #pragma GCC diagnostic push
19
19
  #pragma GCC diagnostic ignored "-Wformat-security"
20
20
  #endif
21
21
 
22
- size_t size = std::snprintf(nullptr, 0, fmt, std::forward<Arg_Ts>(args)...);
22
+ size_t size = std::snprintf(nullptr, 0, fmt, std::forward<Parameter_Ts>(args)...);
23
23
  this->message_ = std::string(size, '\0');
24
24
 
25
25
  // size+1 avoids truncating the string. Otherwise snprintf writes n - 1 characters
26
26
  // to allow space for null character but we don't need that since std::string
27
27
  // will add a null character internally at n + 1
28
- std::snprintf(&this->message_[0], size + 1, fmt, std::forward<Arg_Ts>(args)...);
28
+ std::snprintf(&this->message_[0], size + 1, fmt, std::forward<Parameter_Ts>(args)...);
29
29
 
30
30
  #if defined(__GNUC__) || defined(__clang__)
31
31
  #pragma GCC diagnostic pop
data/rice/NoGVL.hpp ADDED
@@ -0,0 +1,13 @@
1
+ #ifndef Rice__NoGVL__hpp_
2
+ #define Rice__NoGVL__hpp_
3
+
4
+ namespace Rice
5
+ {
6
+ class NoGVL
7
+ {
8
+ public:
9
+ NoGVL() = default;
10
+ };
11
+ } // Rice
12
+
13
+ #endif // Rice__NoGVL__hpp_
@@ -0,0 +1,56 @@
1
+ #ifndef Rice__Reference__hpp_
2
+ #define Rice__Reference__hpp_
3
+
4
+ namespace Rice
5
+ {
6
+ template<typename T>
7
+ class Reference
8
+ {
9
+ static_assert(!detail::is_wrapped_v<detail::intrinsic_type<T>>,
10
+ "Reference can only be used with fundamental types");
11
+
12
+ public:
13
+ Reference();
14
+ Reference(T& data);
15
+ Reference(VALUE value);
16
+ T& get();
17
+
18
+ private:
19
+ T data_;
20
+ };
21
+
22
+ // Specialization needed when VALUE type matches T, causing constructor ambiguity
23
+ // between Reference(T&) and Reference(VALUE). VALUE is unsigned long when
24
+ // SIZEOF_LONG == SIZEOF_VOIDP (Linux/macOS) and unsigned long long when
25
+ // SIZEOF_LONG_LONG == SIZEOF_VOIDP (Windows x64).
26
+ #if SIZEOF_LONG == SIZEOF_VOIDP
27
+ template<>
28
+ class Reference<unsigned long>
29
+ {
30
+ public:
31
+ Reference();
32
+ Reference(unsigned long value, bool isValue = true);
33
+ unsigned long& get();
34
+
35
+ private:
36
+ unsigned long data_;
37
+ };
38
+ #else
39
+ template<>
40
+ class Reference<unsigned long long>
41
+ {
42
+ public:
43
+ Reference();
44
+ Reference(unsigned long long value, bool isValue = true);
45
+ unsigned long long& get();
46
+
47
+ private:
48
+ unsigned long long data_;
49
+ };
50
+ #endif
51
+
52
+ template<typename T>
53
+ Data_Type<Reference<T>> define_reference(std::string klassName = "");
54
+ }
55
+
56
+ #endif // Rice__Reference__hpp_
@@ -0,0 +1,96 @@
1
+ namespace Rice
2
+ {
3
+ template<typename T>
4
+ inline Reference<T>::Reference() : data_{}
5
+ {
6
+ }
7
+
8
+ template<typename T>
9
+ inline Reference<T>::Reference(T& data) : data_(data)
10
+ {
11
+ }
12
+
13
+ template<typename T>
14
+ inline Reference<T>::Reference(VALUE value) : data_(detail::FromRubyFundamental<T>::convert(value))
15
+ {
16
+ }
17
+
18
+ template<typename T>
19
+ inline T& Reference<T>::get()
20
+ {
21
+ return data_;
22
+ }
23
+
24
+ // Specialization implementations - only one is compiled per platform
25
+ #if SIZEOF_LONG == SIZEOF_VOIDP
26
+ // VALUE is unsigned long on Linux/macOS
27
+ inline Reference<unsigned long>::Reference() : data_{}
28
+ {
29
+ }
30
+
31
+ inline Reference<unsigned long>::Reference(unsigned long value, bool isValue) :
32
+ data_(isValue ? detail::FromRubyFundamental<unsigned long>::convert(value) : value)
33
+ {
34
+ }
35
+
36
+ inline unsigned long& Reference<unsigned long>::get()
37
+ {
38
+ return data_;
39
+ }
40
+ #else
41
+ // VALUE is unsigned long long on Windows x64
42
+ inline Reference<unsigned long long>::Reference() : data_{}
43
+ {
44
+ }
45
+
46
+ inline Reference<unsigned long long>::Reference(unsigned long long value, bool isValue) :
47
+ data_(isValue ? detail::FromRubyFundamental<unsigned long long>::convert(value) : value)
48
+ {
49
+ }
50
+
51
+ inline unsigned long long& Reference<unsigned long long>::get()
52
+ {
53
+ return data_;
54
+ }
55
+ #endif
56
+
57
+ template<typename T>
58
+ inline Data_Type<Reference<T>> define_reference(std::string klassName)
59
+ {
60
+ using Reference_T = Reference<T>;
61
+ using Data_Type_T = Data_Type<Reference_T>;
62
+
63
+ if (klassName.empty())
64
+ {
65
+ detail::TypeMapper<Reference_T> typeMapper;
66
+ klassName = typeMapper.rubyName();
67
+ }
68
+
69
+ Module rb_mRice = define_module("Rice");
70
+
71
+ if (Data_Type_T::check_defined(klassName, rb_mRice))
72
+ {
73
+ return Data_Type_T();
74
+ }
75
+
76
+ Data_Type<Reference<T>> result = define_class_under<Reference_T>(rb_mRice, klassName).
77
+ define_constructor(Constructor<Reference_T, T>()).
78
+ define_method("value", &Reference_T::get);
79
+
80
+ return result;
81
+ }
82
+ }
83
+
84
+ namespace Rice::detail
85
+ {
86
+ template<typename T>
87
+ struct Type<Reference<T>>
88
+ {
89
+ static bool verify()
90
+ {
91
+ detail::verifyType<T>();
92
+ define_reference<T>();
93
+ return true;
94
+ }
95
+ };
96
+ }
data/rice/Return.hpp CHANGED
@@ -13,7 +13,10 @@ namespace Rice
13
13
  Return& setValue() override;
14
14
  Return& setOpaque() override;
15
15
  Return& takeOwnership() override;
16
- Return& setBuffer() override;
16
+ };
17
+
18
+ class ReturnBuffer : public Return
19
+ {
17
20
  };
18
21
  } // Rice
19
22
 
data/rice/Return.ipp CHANGED
@@ -29,10 +29,4 @@ namespace Rice
29
29
  Arg::takeOwnership();
30
30
  return *this;
31
31
  }
32
-
33
- inline Return& Return::setBuffer()
34
- {
35
- Arg::setBuffer();
36
- return *this;
37
- }
38
32
  } // Rice
@@ -12,8 +12,8 @@ namespace Rice
12
12
  * Example:
13
13
  * \code
14
14
  * Array a;
15
- * a.push(String("some string"));
16
- * a.push(42);
15
+ * a.push(String("some string"), false);
16
+ * a.push(42, false);
17
17
  * \endcode
18
18
  */
19
19
  class Array
@@ -92,7 +92,7 @@ namespace Rice
92
92
  * \return the object which was pushed onto the array.
93
93
  */
94
94
  template<typename T>
95
- Object push(T&& obj, bool takeOwnership);
95
+ Object push(T&& obj, bool takeOwnership = false);
96
96
 
97
97
  //! Pop an element from the end of the array
98
98
  /*! \return the object which was popped from the array, or Qnil if
@@ -116,6 +116,12 @@ namespace Rice
116
116
  template<typename Array_Ptr_T, typename Value_T>
117
117
  class Iterator;
118
118
 
119
+ // Friend declaration for non-member operator+
120
+ template<typename Array_Ptr_T, typename Value_T>
121
+ friend Iterator<Array_Ptr_T, Value_T> operator+(
122
+ long n,
123
+ Iterator<Array_Ptr_T, Value_T> const& it);
124
+
119
125
  long position_of(long index) const;
120
126
 
121
127
  public:
@@ -164,13 +170,12 @@ namespace Rice
164
170
  long index_;
165
171
  };
166
172
 
167
- //! A helper class for implementing iterators for a Array.
168
- // TODO: This really should be a random-access iterator.
173
+ //! A random-access iterator for Array.
169
174
  template<typename Array_Ptr_T, typename Value_T>
170
175
  class Array::Iterator
171
176
  {
172
177
  public:
173
- using iterator_category = std::forward_iterator_tag;
178
+ using iterator_category = std::random_access_iterator_tag;
174
179
  using value_type = Value_T;
175
180
  using difference_type = long;
176
181
  using pointer = Object*;
@@ -184,17 +189,43 @@ namespace Rice
184
189
  template<typename Array_Ptr_T_, typename Value_T_>
185
190
  Iterator& operator=(Iterator<Array_Ptr_T_, Value_T_> const& rhs);
186
191
 
192
+ // Forward iterator operations
187
193
  Iterator& operator++();
188
194
  Iterator operator++(int);
189
- Value_T operator*();
195
+ Value_T operator*() const;
190
196
  Object* operator->();
191
197
 
198
+ // Bidirectional iterator operations
199
+ Iterator& operator--();
200
+ Iterator operator--(int);
201
+
202
+ // Random access iterator operations
203
+ Iterator& operator+=(difference_type n);
204
+ Iterator& operator-=(difference_type n);
205
+ Iterator operator+(difference_type n) const;
206
+ Iterator operator-(difference_type n) const;
207
+ difference_type operator-(Iterator const& rhs) const;
208
+ Value_T operator[](difference_type n) const;
209
+
210
+ // Comparison operators
192
211
  template<typename Array_Ptr_T_, typename Value_T_>
193
212
  bool operator==(Iterator<Array_Ptr_T_, Value_T_> const& rhs) const;
194
213
 
195
214
  template<typename Array_Ptr_T_, typename Value_T_>
196
215
  bool operator!=(Iterator<Array_Ptr_T_, Value_T_> const& rhs) const;
197
216
 
217
+ template<typename Array_Ptr_T_, typename Value_T_>
218
+ bool operator<(Iterator<Array_Ptr_T_, Value_T_> const& rhs) const;
219
+
220
+ template<typename Array_Ptr_T_, typename Value_T_>
221
+ bool operator>(Iterator<Array_Ptr_T_, Value_T_> const& rhs) const;
222
+
223
+ template<typename Array_Ptr_T_, typename Value_T_>
224
+ bool operator<=(Iterator<Array_Ptr_T_, Value_T_> const& rhs) const;
225
+
226
+ template<typename Array_Ptr_T_, typename Value_T_>
227
+ bool operator>=(Iterator<Array_Ptr_T_, Value_T_> const& rhs) const;
228
+
198
229
  Array_Ptr_T array() const;
199
230
  long index() const;
200
231
 
@@ -204,6 +235,12 @@ namespace Rice
204
235
 
205
236
  Object tmp_;
206
237
  };
238
+
239
+ // Non-member operator+ for n + iterator (allows n + iterator syntax)
240
+ template<typename Array_Ptr_T, typename Value_T>
241
+ Array::Iterator<Array_Ptr_T, Value_T> operator+(
242
+ long n,
243
+ Array::Iterator<Array_Ptr_T, Value_T> const& it);
207
244
  } // namespace Rice
208
245
 
209
246
  #endif // Rice__Array__hpp_