rice 4.5.0 → 4.6.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 (166) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -0
  3. data/CMakeLists.txt +31 -0
  4. data/CMakePresets.json +75 -0
  5. data/COPYING +3 -2
  6. data/FindRuby.cmake +437 -0
  7. data/Rakefile +5 -4
  8. data/include/rice/rice.hpp +5436 -3201
  9. data/include/rice/stl.hpp +2355 -1269
  10. data/lib/make_rice_headers.rb +79 -0
  11. data/lib/mkmf-rice.rb +4 -0
  12. data/lib/rice/version.rb +3 -0
  13. data/lib/rice.rb +1 -0
  14. data/lib/rubygems/builder.rb +11 -0
  15. data/lib/rubygems/cmake_builder.rb +113 -0
  16. data/lib/rubygems_plugin.rb +9 -0
  17. data/rice/Arg.hpp +7 -1
  18. data/rice/Arg.ipp +11 -2
  19. data/rice/Buffer.hpp +123 -0
  20. data/rice/Buffer.ipp +599 -0
  21. data/rice/Constructor.ipp +3 -3
  22. data/rice/Data_Object.hpp +2 -3
  23. data/rice/Data_Object.ipp +188 -188
  24. data/rice/Data_Type.hpp +4 -5
  25. data/rice/Data_Type.ipp +42 -26
  26. data/rice/Enum.hpp +0 -1
  27. data/rice/Enum.ipp +26 -23
  28. data/rice/Init.hpp +8 -0
  29. data/rice/Init.ipp +8 -0
  30. data/rice/MemoryView.ipp +1 -41
  31. data/rice/Return.hpp +1 -1
  32. data/rice/Return.ipp +6 -0
  33. data/rice/cpp_api/Array.hpp +209 -0
  34. data/rice/cpp_api/Array.ipp +304 -0
  35. data/rice/cpp_api/Builtin_Object.hpp +31 -0
  36. data/rice/cpp_api/Builtin_Object.ipp +37 -0
  37. data/rice/cpp_api/Class.hpp +70 -0
  38. data/rice/cpp_api/Class.ipp +97 -0
  39. data/rice/cpp_api/Encoding.hpp +32 -0
  40. data/rice/cpp_api/Encoding.ipp +59 -0
  41. data/rice/cpp_api/Hash.hpp +194 -0
  42. data/rice/cpp_api/Hash.ipp +257 -0
  43. data/rice/cpp_api/Identifier.hpp +46 -0
  44. data/rice/cpp_api/Identifier.ipp +31 -0
  45. data/rice/cpp_api/Module.hpp +72 -0
  46. data/rice/cpp_api/Module.ipp +101 -0
  47. data/rice/cpp_api/Object.hpp +272 -0
  48. data/rice/cpp_api/Object.ipp +235 -0
  49. data/rice/cpp_api/String.hpp +74 -0
  50. data/rice/cpp_api/String.ipp +120 -0
  51. data/rice/cpp_api/Struct.hpp +113 -0
  52. data/rice/cpp_api/Struct.ipp +92 -0
  53. data/rice/cpp_api/Symbol.hpp +46 -0
  54. data/rice/cpp_api/Symbol.ipp +93 -0
  55. data/rice/cpp_api/shared_methods.hpp +134 -0
  56. data/rice/detail/MethodInfo.hpp +1 -9
  57. data/rice/detail/MethodInfo.ipp +5 -72
  58. data/rice/detail/Native.hpp +3 -2
  59. data/rice/detail/Native.ipp +32 -4
  60. data/rice/detail/NativeAttributeGet.hpp +3 -2
  61. data/rice/detail/NativeAttributeGet.ipp +8 -2
  62. data/rice/detail/NativeAttributeSet.hpp +3 -2
  63. data/rice/detail/NativeAttributeSet.ipp +8 -2
  64. data/rice/detail/NativeCallbackFFI.ipp +1 -1
  65. data/rice/detail/NativeFunction.hpp +17 -6
  66. data/rice/detail/NativeFunction.ipp +168 -64
  67. data/rice/detail/NativeIterator.hpp +3 -2
  68. data/rice/detail/NativeIterator.ipp +8 -2
  69. data/rice/detail/RubyType.hpp +2 -5
  70. data/rice/detail/RubyType.ipp +50 -5
  71. data/rice/detail/Type.hpp +3 -1
  72. data/rice/detail/Type.ipp +61 -31
  73. data/rice/detail/Wrapper.hpp +68 -33
  74. data/rice/detail/Wrapper.ipp +103 -113
  75. data/rice/detail/from_ruby.hpp +5 -4
  76. data/rice/detail/from_ruby.ipp +737 -365
  77. data/rice/detail/to_ruby.ipp +1092 -186
  78. data/rice/global_function.ipp +1 -1
  79. data/rice/libc/file.hpp +11 -0
  80. data/rice/libc/file.ipp +32 -0
  81. data/rice/rice.hpp +23 -16
  82. data/rice/stl/complex.hpp +6 -0
  83. data/rice/stl/complex.ipp +93 -0
  84. data/rice/stl/exception.hpp +11 -0
  85. data/rice/stl/exception.ipp +29 -0
  86. data/rice/stl/exception_ptr.hpp +6 -0
  87. data/rice/stl/exception_ptr.ipp +27 -0
  88. data/rice/stl/map.hpp +12 -0
  89. data/rice/stl/map.ipp +469 -0
  90. data/rice/stl/monostate.hpp +6 -0
  91. data/rice/stl/monostate.ipp +80 -0
  92. data/rice/stl/multimap.hpp +14 -0
  93. data/rice/stl/multimap.ipp +448 -0
  94. data/rice/stl/optional.hpp +6 -0
  95. data/rice/stl/optional.ipp +118 -0
  96. data/rice/stl/pair.hpp +13 -0
  97. data/rice/stl/pair.ipp +155 -0
  98. data/rice/stl/reference_wrapper.hpp +6 -0
  99. data/rice/stl/reference_wrapper.ipp +41 -0
  100. data/rice/stl/set.hpp +12 -0
  101. data/rice/stl/set.ipp +495 -0
  102. data/rice/stl/shared_ptr.hpp +28 -0
  103. data/rice/stl/shared_ptr.ipp +224 -0
  104. data/rice/stl/string.hpp +6 -0
  105. data/rice/stl/string.ipp +158 -0
  106. data/rice/stl/string_view.hpp +6 -0
  107. data/rice/stl/string_view.ipp +65 -0
  108. data/rice/stl/tuple.hpp +6 -0
  109. data/rice/stl/tuple.ipp +128 -0
  110. data/rice/stl/type_index.hpp +6 -0
  111. data/rice/stl/type_index.ipp +30 -0
  112. data/rice/stl/type_info.hpp +6 -0
  113. data/rice/stl/type_info.ipp +29 -0
  114. data/rice/stl/unique_ptr.hpp +22 -0
  115. data/rice/stl/unique_ptr.ipp +139 -0
  116. data/rice/stl/unordered_map.hpp +12 -0
  117. data/rice/stl/unordered_map.ipp +469 -0
  118. data/rice/stl/variant.hpp +6 -0
  119. data/rice/stl/variant.ipp +242 -0
  120. data/rice/stl/vector.hpp +12 -0
  121. data/rice/stl/vector.ipp +590 -0
  122. data/rice/stl.hpp +7 -3
  123. data/rice/traits/attribute_traits.hpp +26 -0
  124. data/rice/traits/function_traits.hpp +95 -0
  125. data/rice/traits/method_traits.hpp +47 -0
  126. data/rice/traits/rice_traits.hpp +160 -0
  127. data/rice.gemspec +85 -0
  128. data/test/embed_ruby.cpp +3 -0
  129. data/test/ruby/test_multiple_extensions_same_class.rb +14 -14
  130. data/test/test_Array.cpp +6 -3
  131. data/test/test_Attribute.cpp +34 -1
  132. data/test/test_Buffer.cpp +285 -0
  133. data/test/test_Callback.cpp +2 -3
  134. data/test/test_Data_Object.cpp +88 -34
  135. data/test/test_Data_Type.cpp +106 -65
  136. data/test/test_Director.cpp +7 -3
  137. data/test/test_Enum.cpp +5 -2
  138. data/test/test_File.cpp +1 -1
  139. data/test/test_From_Ruby.cpp +181 -114
  140. data/test/test_Iterator.cpp +1 -1
  141. data/test/{test_JumpException.cpp → test_Jump_Exception.cpp} +1 -0
  142. data/test/test_Keep_Alive.cpp +7 -18
  143. data/test/test_Keep_Alive_No_Wrapper.cpp +0 -1
  144. data/test/test_Module.cpp +13 -6
  145. data/test/test_Native_Registry.cpp +0 -1
  146. data/test/test_Overloads.cpp +180 -5
  147. data/test/test_Ownership.cpp +100 -57
  148. data/test/test_Proc.cpp +0 -1
  149. data/test/test_Self.cpp +4 -4
  150. data/test/test_Stl_Map.cpp +37 -39
  151. data/test/test_Stl_Multimap.cpp +693 -0
  152. data/test/test_Stl_Pair.cpp +8 -8
  153. data/test/test_Stl_Reference_Wrapper.cpp +4 -2
  154. data/test/test_Stl_Set.cpp +790 -0
  155. data/test/{test_Stl_SmartPointer.cpp → test_Stl_SharedPtr.cpp} +97 -127
  156. data/test/test_Stl_Tuple.cpp +116 -0
  157. data/test/test_Stl_Type.cpp +1 -1
  158. data/test/test_Stl_UniquePtr.cpp +202 -0
  159. data/test/test_Stl_Unordered_Map.cpp +28 -34
  160. data/test/test_Stl_Variant.cpp +217 -89
  161. data/test/test_Stl_Vector.cpp +209 -83
  162. data/test/test_To_Ruby.cpp +373 -1
  163. data/test/test_Type.cpp +85 -14
  164. data/test/test_global_functions.cpp +17 -4
  165. metadata +94 -10
  166. data/rice/detail/TupleIterator.hpp +0 -14
data/rice/Data_Type.ipp CHANGED
@@ -3,7 +3,7 @@
3
3
  namespace Rice
4
4
  {
5
5
  template<typename T>
6
- inline void ruby_mark_internal(detail::Wrapper* wrapper)
6
+ inline void ruby_mark_internal(detail::WrapperBase* wrapper)
7
7
  {
8
8
  // Tell the wrapper to mark the objects its keeping alive
9
9
  wrapper->ruby_mark();
@@ -14,7 +14,7 @@ namespace Rice
14
14
  }
15
15
 
16
16
  template<typename T>
17
- inline void ruby_free_internal(detail::Wrapper* wrapper)
17
+ inline void ruby_free_internal(detail::WrapperBase* wrapper)
18
18
  {
19
19
  delete wrapper;
20
20
  }
@@ -59,12 +59,12 @@ namespace Rice
59
59
  // Now register with the type registry
60
60
  detail::Registries::instance.types.add<T>(klass_, rb_data_type_);
61
61
 
62
- auto iter = Data_Type<T>::unbound_instances_.begin();
63
- while (iter != Data_Type<T>::unbound_instances_.end())
62
+ auto instances = unbound_instances();
63
+ for (auto instance: instances)
64
64
  {
65
- (*iter)->set_value(klass);
66
- iter = Data_Type<T>::unbound_instances_.erase(iter);
65
+ instance->set_value(klass);
67
66
  }
67
+ instances.clear();
68
68
 
69
69
  return Data_Type<T>();
70
70
  }
@@ -84,12 +84,26 @@ namespace Rice
84
84
  rb_data_type_ = nullptr;
85
85
  }
86
86
 
87
+ // Track unbound instances (ie, declared variables of type Data_Type<T>
88
+ // before define_class is called). We can't simply use a static inline
89
+ // member because it sometimes crashes clang and gcc (msvc seems fine)
87
90
  template<typename T>
88
- inline Data_Type<T>::Data_Type() : Class(klass_ == Qnil ? rb_cObject : klass_)
91
+ inline std::set<Data_Type<T>*>& Data_Type<T>::unbound_instances()
89
92
  {
90
- if (!is_bound())
93
+ static std::set<Data_Type<T>*> unbound_instances;
94
+ return unbound_instances;
95
+ }
96
+
97
+ template<typename T>
98
+ inline Data_Type<T>::Data_Type()
99
+ {
100
+ if (is_bound())
91
101
  {
92
- this->unbound_instances_.insert(this);
102
+ this->set_value(klass_);
103
+ }
104
+ else
105
+ {
106
+ unbound_instances().insert(this);
93
107
  }
94
108
  }
95
109
 
@@ -172,7 +186,7 @@ namespace Rice
172
186
  template<typename Director_T>
173
187
  inline Data_Type<T>& Data_Type<T>::define_director()
174
188
  {
175
- if (!detail::Registries::instance.types.isDefined<Director_T>())
189
+ if (!Data_Type<Director_T>::is_defined())
176
190
  {
177
191
  Data_Type<Director_T>::bind(*this);
178
192
  }
@@ -207,24 +221,26 @@ namespace Rice
207
221
  }
208
222
 
209
223
  template<typename T>
210
- inline bool Data_Type<T>::is_defined(Object parent, const std::string& name)
224
+ inline bool Data_Type<T>::is_defined()
211
225
  {
212
- // Is the class already defined?
213
- if (detail::Registries::instance.types.isDefined<T>())
214
- {
215
- Data_Type<T> result = Data_Type<T>();
216
-
217
- // If this redefinition is a different name then create a new constant
218
- if (result.name() != name)
219
- {
220
- detail::protect(rb_define_const, parent, name.c_str(), result.klass());
221
- }
226
+ return detail::Registries::instance.types.isDefined<T>();
227
+ }
222
228
 
229
+ template<typename T>
230
+ inline bool Data_Type<T>::check_defined(const std::string& name, Object parent)
231
+ {
232
+ if (Data_Type<T>::is_defined())
233
+ {
234
+ Data_Type<T> dataType;
235
+ parent.const_set_maybe(name, dataType.klass());
223
236
  return true;
224
237
  }
225
- return false;
238
+ else
239
+ {
240
+ return false;
241
+ }
226
242
  }
227
-
243
+
228
244
  template<typename Base_T>
229
245
  inline Class get_superklass()
230
246
  {
@@ -247,7 +263,7 @@ namespace Rice
247
263
  template<typename T, typename Base_T>
248
264
  inline Data_Type<T> define_class_under(Object parent, Identifier id, Class superKlass)
249
265
  {
250
- if (Rice::Data_Type<T>::is_defined(parent, id.str()))
266
+ if (Rice::Data_Type<T>::check_defined(id.str(), parent))
251
267
  {
252
268
  return Data_Type<T>();
253
269
  }
@@ -270,7 +286,7 @@ namespace Rice
270
286
  {
271
287
  std::string klassName(name);
272
288
 
273
- if (Rice::Data_Type<T>::is_defined(rb_cObject, klassName))
289
+ if (Rice::Data_Type<T>::check_defined(klassName))
274
290
  {
275
291
  return Data_Type<T>();
276
292
  }
@@ -308,7 +324,7 @@ namespace Rice
308
324
  using Attr_T = typename detail::NativeAttributeSet<Attribute_T>::Attr_T;
309
325
  if constexpr (!std::is_const_v<Attr_T> &&
310
326
  (std::is_fundamental_v<Attr_T> || std::is_assignable_v<Attr_T, Attr_T>))
311
- {
327
+ {
312
328
  // Define native attribute setter
313
329
  if (access == AttrAccess::ReadWrite || access == AttrAccess::Write)
314
330
  detail::NativeAttributeSet<Attribute_T>::define(klass_, name, std::forward<Attribute_T>(attribute));
data/rice/Enum.hpp CHANGED
@@ -30,7 +30,6 @@ namespace Rice
30
30
  using Underlying_T = std::underlying_type_t<Enum_T>;
31
31
 
32
32
  public:
33
-
34
33
  Enum() = default;
35
34
 
36
35
  //! Construct and initialize.
data/rice/Enum.ipp CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  #include <stdexcept>
3
2
 
4
3
  namespace Rice
@@ -29,44 +28,48 @@ namespace Rice
29
28
  // First we need a constructor
30
29
  klass.define_constructor(Constructor<Enum_T>());
31
30
 
32
- // Instance methods. The self parameter is confusing because it is really a Data_Object<Enum_T>.
33
- // However, if we make that the type then the From_Ruby code will consider it a
34
- // Data_Type<Data_Object<Enum_T>>>. But in define class above it was actually bound as
35
- // Data_Type<Enum_T>. Thus the static_casts in the methods below.
36
- klass.define_method("to_s", [](Enum_T& notSelf)
31
+ klass.define_method("to_s", [](Enum_T& self) -> String
37
32
  {
38
- // We have to return string because we don't know if std::string support has
39
- // been included by the user
40
- Data_Object<Enum_T> self = static_cast<Data_Object<Enum_T>>(notSelf);
41
- return String(valuesToNames_[*self]);
33
+ return String(valuesToNames_[self]);
42
34
  })
43
- .define_method("to_int", [](Enum_T& notSelf) -> Underlying_T
35
+ .define_method("to_int", [](Enum_T& self) -> Underlying_T
44
36
  {
45
- Data_Object<Enum_T> self = static_cast<Data_Object<Enum_T>>(notSelf);
46
- return static_cast<Underlying_T>(*self);
37
+ return (Underlying_T)(self);
47
38
  })
48
- .define_method("inspect", [](Enum_T& notSelf)
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
+
45
+ Colors::Red | Colors:Blue | Colors:Green
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;
50
+
51
+ Array result;
52
+ result.push(self);
53
+ result.push(otherEnum);
54
+ return result;
55
+ })
56
+ .define_method("inspect", [](Enum_T& self)
49
57
  {
50
- Data_Object<Enum_T> self = static_cast<Data_Object<Enum_T>>(notSelf);
51
-
52
58
  std::stringstream result;
53
59
  VALUE rubyKlass = Enum<Enum_T>::klass().value();
54
60
  result << "#<" << detail::protect(rb_class2name, rubyKlass)
55
- << "::" << Enum<Enum_T>::valuesToNames_[*self] << ">";
61
+ << "::" << Enum<Enum_T>::valuesToNames_[self] << ">";
56
62
 
57
63
  // We have to return string because we don't know if std::string support has
58
64
  // been included by the user
59
65
  return String(result.str());
60
66
  })
61
- .define_method("hash", [](Enum_T& notSelf) -> Underlying_T
67
+ .define_method("hash", [](Enum_T& self) -> Underlying_T
62
68
  {
63
- Data_Object<Enum_T> self = static_cast<Data_Object<Enum_T>>(notSelf);
64
- return (Underlying_T)*self;
69
+ return (Underlying_T)self;
65
70
  })
66
- .define_method("eql?", [](Enum_T& notSelf, Enum_T& notOther)
71
+ .define_method("eql?", [](Enum_T& self, Enum_T& other)
67
72
  {
68
- Data_Object<Enum_T> self = static_cast<Data_Object<Enum_T>>(notSelf);
69
- Data_Object<Enum_T> other = static_cast<Data_Object<Enum_T>>(notOther);
70
73
  return self == other;
71
74
  });
72
75
 
data/rice/Init.hpp ADDED
@@ -0,0 +1,8 @@
1
+ #ifndef Rice__Init__hpp_
2
+ #define Rice__Init__hpp_
3
+
4
+ namespace Rice
5
+ {
6
+ void init();
7
+ }
8
+ #endif // Rice__Init__hpp_
data/rice/Init.ipp ADDED
@@ -0,0 +1,8 @@
1
+ namespace Rice
2
+ {
3
+ inline void init()
4
+ {
5
+ detail::define_ruby_types();
6
+ define_fundamental_buffer_types();
7
+ };
8
+ }
data/rice/MemoryView.ipp CHANGED
@@ -1,43 +1,3 @@
1
1
  namespace Rice
2
2
  {
3
- }
4
-
5
- namespace Rice::detail
6
- {
7
- template<>
8
- class To_Ruby<unsigned char**>
9
- {
10
- public:
11
- VALUE convert(unsigned char** x)
12
- {
13
- std::runtime_error("To_Ruby unsigned char** is not implemented yet");
14
- return Qnil;
15
- }
16
- };
17
-
18
- template<>
19
- class From_Ruby<unsigned char**>
20
- {
21
- public:
22
- From_Ruby() = default;
23
-
24
- explicit From_Ruby(Arg* arg) : arg_(arg)
25
- {
26
- }
27
-
28
- Convertible is_convertible(VALUE value)
29
- {
30
- std::runtime_error("From_Ruby unsigned char** is not implemented yet");
31
- return Convertible::None;
32
- }
33
-
34
- unsigned char** convert(VALUE value)
35
- {
36
- std::runtime_error("From_Ruby unsigned char** is not implemented yet");
37
- return nullptr;
38
- }
39
-
40
- private:
41
- Arg* arg_ = nullptr;
42
- };
43
- }
3
+ }
data/rice/Return.hpp CHANGED
@@ -13,7 +13,7 @@ namespace Rice
13
13
  Return& setValue() override;
14
14
  Return& setOpaque() override;
15
15
  Return& takeOwnership() override;
16
-
16
+ Return& setArray() override;
17
17
  };
18
18
  } // Rice
19
19
 
data/rice/Return.ipp CHANGED
@@ -29,4 +29,10 @@ namespace Rice
29
29
  Arg::takeOwnership();
30
30
  return *this;
31
31
  }
32
+
33
+ inline Return& Return::setArray()
34
+ {
35
+ Arg::setArray();
36
+ return *this;
37
+ }
32
38
  } // Rice
@@ -0,0 +1,209 @@
1
+ #ifndef Rice__Array__hpp_
2
+ #define Rice__Array__hpp_
3
+
4
+ #include <iterator>
5
+ #include <memory>
6
+
7
+ namespace Rice
8
+ {
9
+ //! A wrapper for the ruby Array class.
10
+ /*! This class provides a C++-style interface to ruby's Array class and
11
+ * its associated rb_ary_* functions.
12
+ * Example:
13
+ * \code
14
+ * Array a;
15
+ * a.push(String("some string"));
16
+ * a.push(42);
17
+ * \endcode
18
+ */
19
+ class Array
20
+ : public Builtin_Object<T_ARRAY>
21
+ {
22
+ public:
23
+ //! Construct a new array
24
+ Array();
25
+
26
+ //! Construct a new array with specified size
27
+ Array(long capacity);
28
+
29
+ //! Wrap an existing array
30
+ /*! \param v a ruby object, which must be of type T_ARRAY.
31
+ */
32
+ Array(Object v);
33
+
34
+ //! Wrap an existing array
35
+ /*! \param v a ruby object, which must be of type T_ARRAY.
36
+ */
37
+ Array(VALUE v);
38
+
39
+ //! Construct an array from a sequence.
40
+ /*! \param begin an iterator to the beginning of the sequence.
41
+ * \param end an iterator to the end of the sequence.
42
+ */
43
+ template<typename Iter_T>
44
+ Array(Iter_T begin, Iter_T end);
45
+
46
+ //! Construct an Array from a C array.
47
+ /*! \param a a C array of type T and size n.
48
+ */
49
+ template<typename T, long n>
50
+ Array(T const (&a)[n]);
51
+
52
+ public:
53
+ //! Return the size of the array.
54
+ long size() const;
55
+
56
+ //! Return the element at the given index.
57
+ /*! \param index The index of the desired element. The index may be
58
+ * negative, to indicate an offset from the end of the array. If the
59
+ * index is out of bounds, this function has undefined behavior.
60
+ * \return the element at the given index.
61
+ */
62
+ Object operator[](long index) const;
63
+
64
+ //! Converts a Ruby Array into a C++ array where the elements are
65
+ //! contiguous. This is similar to a std::vector, but instead a
66
+ //! std::unique_ptr<T> is returned. This allows the calling code to
67
+ //! pass ownership to its callers if needed (for exmaple, From_Ruby<T>#convert)
68
+ //! Note this method is designed convenience, not for speed or efficieny.
69
+ //! C++ APIs that take large chunks of memory should not be passed Ruby Arrrays.
70
+ //! \return std::unique_ptr that is owned by the caller.
71
+ template<typename T>
72
+ String pack();
73
+
74
+ // Join elements together
75
+ String join(const char* separator);
76
+
77
+ private:
78
+ //! A helper class so array[index]=value can work.
79
+ class Proxy;
80
+
81
+ public:
82
+ //! Return a reference to the element at the given index.
83
+ /*! \param index The index of the desired element. The index may be
84
+ * negative, to indicate an offset from the end of the array. If the
85
+ * index is out of bounds, this function has undefined behavior.
86
+ * \return the element at the given index.
87
+ */
88
+ Proxy operator[](long index);
89
+
90
+ //! Push an element onto the end of the array
91
+ /*! \param v an object to push onto the array.
92
+ * \return the object which was pushed onto the array.
93
+ */
94
+ template<typename T>
95
+ Object push(T obj);
96
+
97
+ //! Pop an element from the end of the array
98
+ /*! \return the object which was popped from the array, or Qnil if
99
+ * the array was empty.
100
+ */
101
+ Object pop();
102
+
103
+ //! Unshift an element onto the beginning of the array
104
+ /*! \param v an object to unshift onto the array.
105
+ * \return the object which was unshifted onto the array.
106
+ */
107
+ template<typename T>
108
+ Object unshift(T const& obj);
109
+
110
+ //! Shift an element from the beginning of the array
111
+ /*! \return the object which was shifted from the array.
112
+ */
113
+ Object shift();
114
+
115
+ private:
116
+ template<typename Array_Ptr_T, typename Value_T>
117
+ class Iterator;
118
+
119
+ long position_of(long index) const;
120
+
121
+ public:
122
+ //! An iterator.
123
+ typedef Iterator<Array*, Proxy> iterator;
124
+
125
+ //! A const iterator.
126
+ typedef Iterator<Array const*, Object> const_iterator;
127
+
128
+ //! Return an iterator to the beginning of the array.
129
+ iterator begin();
130
+
131
+ //! Return a const iterator to the beginning of the array.
132
+ const_iterator begin() const;
133
+
134
+ //! Return an iterator to the end of the array.
135
+ iterator end();
136
+
137
+ //! Return a const iterator to the end of the array.
138
+ const_iterator end() const;
139
+
140
+ //! Return the content of the array as a std::vector
141
+ template<typename T>
142
+ std::vector<T> to_vector();
143
+ };
144
+
145
+ //! A helper class so array[index]=value can work.
146
+ class Array::Proxy
147
+ {
148
+ public:
149
+ //! Construct a new Proxy
150
+ Proxy(Array array, long index);
151
+
152
+ //! Implicit conversions
153
+ operator Object() const;
154
+
155
+ //! Explicit conversion to VALUE.
156
+ VALUE value() const;
157
+
158
+ //! Assignment operator.
159
+ template<typename T>
160
+ Object operator=(T const& value);
161
+
162
+ private:
163
+ Array array_;
164
+ long index_;
165
+ };
166
+
167
+ //! A helper class for implementing iterators for a Array.
168
+ // TODO: This really should be a random-access iterator.
169
+ template<typename Array_Ptr_T, typename Value_T>
170
+ class Array::Iterator
171
+ {
172
+ public:
173
+ using iterator_category = std::forward_iterator_tag;
174
+ using value_type = Value_T;
175
+ using difference_type = long;
176
+ using pointer = Object*;
177
+ using reference = Value_T&;
178
+
179
+ Iterator(Array_Ptr_T array, long index);
180
+
181
+ template<typename Array_Ptr_T_, typename Value_T_>
182
+ Iterator(Iterator<Array_Ptr_T_, Value_T_> const& rhs);
183
+
184
+ template<typename Array_Ptr_T_, typename Value_T_>
185
+ Iterator& operator=(Iterator<Array_Ptr_T_, Value_T_> const& rhs);
186
+
187
+ Iterator& operator++();
188
+ Iterator operator++(int);
189
+ Value_T operator*();
190
+ Object* operator->();
191
+
192
+ template<typename Array_Ptr_T_, typename Value_T_>
193
+ bool operator==(Iterator<Array_Ptr_T_, Value_T_> const& rhs) const;
194
+
195
+ template<typename Array_Ptr_T_, typename Value_T_>
196
+ bool operator!=(Iterator<Array_Ptr_T_, Value_T_> const& rhs) const;
197
+
198
+ Array_Ptr_T array() const;
199
+ long index() const;
200
+
201
+ private:
202
+ Array_Ptr_T array_;
203
+ long index_;
204
+
205
+ Object tmp_;
206
+ };
207
+ } // namespace Rice
208
+
209
+ #endif // Rice__Array__hpp_